1"use strict";(globalThis.webpackChunkredstone_docs||=[]).push([[26],{438(e,n,t){t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>c,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"technical-reference/non-evm-chains/sui/typescript-tutorial","title":"How to use in TypeScript","description":"1. Read firstly the docs from How to start section","source":"@site/docs/technical-reference/non-evm-chains/sui/typescript-tutorial.md","sourceDirName":"technical-reference/non-evm-chains/sui","slug":"/technical-reference/non-evm-chains/sui/typescript-tutorial","permalink":"/docs/technical-reference/non-evm-chains/sui/typescript-tutorial","draft":false,"unlisted":false,"editUrl":"https://github.com/redstone-finance/redstone-docs/tree/main/docs/technical-reference/non-evm-chains/sui/typescript-tutorial.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2,"sidebar_label":"How to use in TypeScript"},"sidebar":"tutorialSidebar","previous":{"title":"How to use in Move","permalink":"/docs/technical-reference/non-evm-chains/sui/move-tutorial"},"next":{"title":"Security","permalink":"/docs/category/security"}}');var s=t(4848),r=t(8453);const c={sidebar_position:2,sidebar_label:"How to use in TypeScript"},o="How to use in TypeScript",a={},d=[{value:"Dependencies",id:"dependencies",level:2},{value:"Reading Prices",id:"reading-prices",level:2},{value:"Example",id:"example",level:2},{value:"Testing",id:"testing",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"how-to-use-in-typescript",children:"How to use in TypeScript"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Read firstly the docs from ",(0,s.jsx)(n.a,{href:"../",children:"How to start"})," section"]}),"\n",(0,s.jsxs)(n.li,{children:["The full source of the package is available ",(0,s.jsx)(n.a,{href:"https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/sui-connector/src",children:"here"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.strong,{children:"info described there"})," is mostly ",(0,s.jsx)(n.strong,{children:"NOT REPEATED below"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"dependencies",children:"Dependencies"}),"\n",(0,s.jsxs)(n.p,{children:["Use the following dependency to embed the ",(0,s.jsx)(n.em,{children:"RedStone Sui Connector"})," into TypeScript."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "dependencies": {\n "@redstone-finance/sui-connector": "1.0.0"\n }\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"reading-prices",children:"Reading Prices"}),"\n",(0,s.jsxs)(n.p,{children:["Reads go through ",(0,s.jsx)(n.code,{children:"SuiContractAdapter"}),", which wraps a ",(0,s.jsx)(n.a,{href:"https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/sui-connector/src/adapter/SuiPricesContractReader.ts",children:(0,s.jsx)(n.code,{children:"SuiPricesContractReader"})})," pointed at the deployed ",(0,s.jsx)(n.code,{children:"PriceAdapter"})," object:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:'import {\n SuiClientBuilder,\n SuiContractAdapter,\n readSuiConfig,\n} from "@redstone-finance/sui-connector";\n\nconst suiClient = new SuiClientBuilder()\n .withSuiNetwork(network)\n .withRpcUrls(rpcUrls)\n .build();\n\nconst adapter = new SuiContractAdapter(suiClient, readSuiConfig(network));\n\nconst prices = await adapter.readContractData(["BTC", "ETH"]);\n'})}),"\n",(0,s.jsxs)(n.p,{children:["See the ",(0,s.jsx)(n.a,{href:"https://app.redstone.finance/push-feeds?networks=sui",children:"RedStone App"})," for the full list of feeds currently supported on Sui and their update parameters."]}),"\n",(0,s.jsxs)(n.p,{children:["Feed IDs are passed as plain strings (",(0,s.jsx)(n.code,{children:'"BTC"'}),") \u2014 the connector zero-pads them to 32 bytes internally (",(0,s.jsx)(n.code,{children:"makeFeedIdBytes"})," in ",(0,s.jsx)(n.a,{href:"https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/sui-connector/src/util.ts",children:(0,s.jsx)(n.code,{children:"util.ts"})}),") before matching them against the on-chain key. This is the same encoding a Move caller has to replicate by hand \u2014 see the ",(0,s.jsx)(n.a,{href:"/docs/technical-reference/non-evm-chains/sui/move-tutorial#contract-interface",children:"Move tutorial"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Two things the snippet above glosses over, both of which matter to get a working c
1all:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsxs)(n.strong,{children:[(0,s.jsx)(n.code,{children:"rpcUrls"})," must select the gRPC client."]})," Public JSON-RPC fullnodes have deprecated the batched ",(0,s.jsx)(n.code,{children:"multiGetObjects"})," method the connector relies on, so a plain ",(0,s.jsx)(n.code,{children:"https://fullnode.mainnet.sui.io:443"})," URL fails with ",(0,s.jsx)(n.code,{children:"Method not found"}),". Force gRPC by appending ",(0,s.jsx)(n.code,{children:"#type=grpc"})," to the URL \u2014 see ",(0,s.jsx)(n.a,{href:"https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/sui-connector/src/client/SuiApi.ts",children:(0,s.jsx)(n.code,{children:"SuiApi.parseUrl"})}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsxs)(n.strong,{children:[(0,s.jsx)(n.code,{children:"readSuiConfig(network)"})," needs ",(0,s.jsx)(n.code,{children:"DEPLOY_DIR"})," set"]})," to the ",(0,s.jsx)(n.code,{children:"suiMultiFeed"})," deployment. Its default (",(0,s.jsx)(n.code,{children:"sui/contracts/price_adapter"}),") points at an older, single-feed deployment and won't resolve the mainnet addresses listed in the ",(0,s.jsx)(n.a,{href:"/docs/technical-reference/non-evm-chains/sui/move-tutorial#deployed-addresses-suimultifeed-mainnet",children:"Move tutorial"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(n.p,{children:"A minimal script that connects to mainnet and reads the BTC and ETH prices:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:'import {\n SuiClientBuilder,\n SuiContractAdapter,\n readSuiConfig,\n} from "@redstone-finance/sui-connector";\n\nconst NETWORK = "mainnet";\n// #type=grpc forces the gRPC client \u2014 the JSON-RPC path is deprecated on public fullnodes\nconst RPC_URLS = ["https://fullnode.mainnet.sui.io:443#type=grpc"];\n\nasync function main() {\n const suiClient = new SuiClientBuilder()\n .withSuiNetwork(NETWORK)\n .withRpcUrls(RPC_URLS)\n .build();\n\n const adapter = new SuiContractAdapter(suiClient, readSuiConfig(NETWORK));\n\n const prices = await adapter.readContractData(["BTC", "ETH"]);\n\n console.log(prices);\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n'})}),"\n",(0,s.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,s.jsxs)(n.p,{children:["Reading prices is a plain RPC call against the already-deployed ",(0,s.jsx)(n.code,{children:"PriceAdapter"})," object \u2014 no wallet, gas, or publishing needed. Install the dependency and run the script directly, with ",(0,s.jsx)(n.code,{children:"DEPLOY_DIR"})," pointed at the ",(0,s.jsx)(n.code,{children:"suiMultiFeed"})," deployment:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'yarn add @redstone-finance/sui-connector\nDEPLOY_DIR="sui/deployments/suiMultiFeed/price_adapter" yarn tsx read-prices.ts\n'})}),"\n",(0,s.jsxs)(n.p,{children:["This returns the raw on-chain values (",(0,s.jsx)(n.code,{children:"lastValue"})," is ",(0,s.jsx)(n.code,{children:"u256"}),", 8 decimals \u2014 divide by ",(0,s.jsx)(n.code,{children:"1e8"}),"), for example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"{\n BTC: { lastDataPackageTimestampMS: ..., lastBlockTimestampMS: ..., lastValue: 7935541000000n },\n ETH: { lastDataPackageTimestampMS: ..., lastBlockTimestampMS: ..., lastValue: 248793355693n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To cross-check a value returned here against the raw on-chain call, use the Move-side ",(0,s.jsx)(n.code,{children:"dev-inspect"})," recipe in the ",(0,s.jsx)(n.a,{href:"/docs/technical-reference/non-evm-chains/sui/move-tutorial#testing-without-publishing",children:"Move tutorial"})," \u2014 both read the same ",(0,s.jsx)(n.code,{children:"PriceAdapter"})," object and should agree."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453(e,n,t){t.d(n,{R:()=>c,x:()=>o});var i=t(6540);const s={},r=i.createContext(s);function c(e){const n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.