From 240e52391c2a0426e2e109b2de50569f9095fca0 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Sat, 13 Jul 2024 20:04:46 +0100 Subject: [PATCH 1/3] feat: Retrieve and Use Boxes --- docs/.vitepress/config.ts | 5 +- docs/use-of-boxes.md | 104 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 docs/use-of-boxes.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 8581709..0aac920 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -36,7 +36,7 @@ function nav(): DefaultTheme.NavItem[] { items: [ { text: "Fleet SDK", - link: "https://github.com/fleet-sdk/fleet/blob/master/CONTRIBUTING.md", + link: "https://github.com/fleet-sdk/fleet/blob/master/CONTRIBUTING.md" }, { text: "Documentation", @@ -60,7 +60,8 @@ function sidebarGuide() { items: [ { text: "Wallet interaction", link: "/wallet-interaction" }, { text: "Transaction building", link: "/transaction-building" }, - { text: "Token burning", link: "/token-burning" } + { text: "Token burning", link: "/token-burning" }, + { text: "Retrieve and Use Boxes", link: "/use-of-boxes" } ] } ]; diff --git a/docs/use-of-boxes.md b/docs/use-of-boxes.md new file mode 100644 index 0000000..b36fafe --- /dev/null +++ b/docs/use-of-boxes.md @@ -0,0 +1,104 @@ +# Retrieve and Use Boxes + +When using the `TransactionBuilder` class, you will need to work with boxes, which are the fundamental building blocks of Ergo transactions. Boxes represent unspent transaction outputs (UTXOs) on the Ergo blockchain. Each box contains assets (such as ERG or tokens) and potentially additional data. + +Boxes are created as outputs when a transaction is executed. They remain on the blockchain as unspent boxes until they are consumed (spent) as inputs in a subsequent transaction. When a box is used as an input, it is effectively destroyed, and new boxes are created as outputs of that transaction. This process forms the UTXO model that Ergo uses, where the blockchain's state is represented by the set of all unspent boxes at any given time + +### Retrieving Boxes from the Connected Wallet + +Ergo provides a blockchain explorer that allows you to query the blockchain for boxes that match specific criteria. You can use the explorer to retrieve boxes that you own or that you want to interact with in your transactions. + +Listing Unspent Boxes + +```ts +await ergo.get_utxos(); +``` + +Structured as an array of objects, each box contains the following fields: + +```ts +{ + boxId: string, + value: string, + assets: Array<{ + tokenId: string, + amount: string + }>, + creationHeight: number, + ergoTree: string, + additionalRegisters: Record, + transactionId: string, + index: number +} +``` + +### Retrieving Boxes from the Blockchain Explorer + +You can also use the blockchain explorer to retrieve boxes that you do not own. This can be useful when you want to interact with specific boxes in your transactions. + +Ergo provides an [API](https://api.ergoplatform.com/api/v1/docs/#operation/getApiV1BoxesUnspentByaddressP1) that allows you to query the blockchain for boxes that match specific criteria. You can use this API to retrieve boxes by address, token, or other criteria. + +Full documentation for the API can be found [here](https://api.ergoplatform.com/api/v1/docs/). + +Listing Boxes by Address from the Explorer + +```ts +function fetchUnspentBoxes(address) { + const url = `https://api.ergoplatform.com/api/v1/boxes/unspent/byAddress/${address}`; + + const headers = { + accept: "application/json" + }; + return fetch(url, { headers: headers }) + .then((response) => response.json()) + .catch((err) => console.error(err)); +} +``` + +### Parsing Box to Input in Transactions + +The Box Data gotten from this API has some extra fields that we need to take out for it to fulfil the interface for boxes. + +```ts +(async () => { + if (await ergoConnector.nautilus.connect()) { + const height = await ergo.get_current_height(); + + const boxFromExplorer = await fetchUnspentBoxes( + await ergo.get_change_address() + ); + const boxes = boxFromExplorer.map((box) => { + return { + boxId: box.boxId, + value: box.value, + assets: box.assets, + creationHeight: box.creationHeight, + ergoTree: box.ergoTree, + additionalRegisters: box.additionalRegisters, + transactionId: box.transactionId, + index: box.index, + }; + }); + + const unsignedTx = new TransactionBuilder(height) + .from(boxes) + .to( + new OutputBuilder( + '100000000', + '9efPWBBjL1pddkH9pxnEjjGZxABseEjeXAAMxMUSV7Ug6nN44Wr' + ) + ) + .sendChangeTo(await ergo.get_change_address()) + .payMinFee() + .build() + .toEIP12Object(); + + const signedTx = await ergo.sign_tx(unsignedTx); + const txId = await ergo.submit_tx(signedTx); + + console.log(txId); + } +})(); +``` + +An example of this implementation can be found [here](https://stackblitz.com/edit/typescript-atujdp?file=index.ts) From c31aff99caf508242bab9b5169eada6d43938d82 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Sat, 13 Jul 2024 20:29:44 +0100 Subject: [PATCH 2/3] chore: re-arrange retrieval docs --- docs/.vitepress/config.ts | 8 +++- docs/{use-of-boxes.md => retrieving-boxes.md} | 44 ++++++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) rename docs/{use-of-boxes.md => retrieving-boxes.md} (72%) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 0aac920..20745bf 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -61,7 +61,13 @@ function sidebarGuide() { { text: "Wallet interaction", link: "/wallet-interaction" }, { text: "Transaction building", link: "/transaction-building" }, { text: "Token burning", link: "/token-burning" }, - { text: "Retrieve and Use Boxes", link: "/use-of-boxes" } + ] + }, + { + text: "Box Retrieval from Blockchain", + collapsible: false, + items: [ + { text: "Retrieving boxes from blockchain", link: "/retrieving-boxes" } ] } ]; diff --git a/docs/use-of-boxes.md b/docs/retrieving-boxes.md similarity index 72% rename from docs/use-of-boxes.md rename to docs/retrieving-boxes.md index b36fafe..6a0e676 100644 --- a/docs/use-of-boxes.md +++ b/docs/retrieving-boxes.md @@ -40,18 +40,39 @@ Ergo provides an [API](https://api.ergoplatform.com/api/v1/docs/#operation/getAp Full documentation for the API can be found [here](https://api.ergoplatform.com/api/v1/docs/). -Listing Boxes by Address from the Explorer +#### Listing Boxes by Address from the Explorer [API](https://api.ergoplatform.com/api/v1/docs/#operation/getApiV1BoxesUnspentByaddressP1) ```ts -function fetchUnspentBoxes(address) { +async function fetchUnspentBoxesByAddress(address): Promise { const url = `https://api.ergoplatform.com/api/v1/boxes/unspent/byAddress/${address}`; const headers = { accept: "application/json" }; - return fetch(url, { headers: headers }) - .then((response) => response.json()) - .catch((err) => console.error(err)); + let rawBoxes = (await ( + await fetch(url, { headers: headers }) + ).json()) as unknown as { + items: Box[]; + }; + return rawBoxes.items; +} +``` + +#### Listing Boxes by Token from the Explorer [API](https://api.ergoplatform.com/api/v1/docs/#operation/getApiV1BoxesUnspentBytokenidP1) + +```ts +async function fetchUnspentBoxesByTokenId(tokenId): Promise { + const url = `https://api.ergoplatform.com/api/v1/boxes/unspent/byTokenId/${tokenId}`; + + const headers = { + accept: "application/json" + }; + let rawBoxes = (await ( + await fetch(url, { headers: headers }) + ).json()) as unknown as { + items: Box[]; + }; + return rawBoxes.items; } ``` @@ -64,10 +85,13 @@ The Box Data gotten from this API has some extra fields that we need to take out if (await ergoConnector.nautilus.connect()) { const height = await ergo.get_current_height(); - const boxFromExplorer = await fetchUnspentBoxes( + const _boxes = await fetchUnspentBoxesByAddress( await ergo.get_change_address() ); - const boxes = boxFromExplorer.map((box) => { + // const _boxes = await fetchUnspentBoxesByAddress( + // "f60bff91f7ae3f3a5f0c2d35b46ef8991f213a61d7f7e453d344fa52a42d9f9a" // SigUSD Token ID + // ); + const boxes = _boxes.map((box) => { return { boxId: box.boxId, value: box.value, @@ -76,7 +100,7 @@ The Box Data gotten from this API has some extra fields that we need to take out ergoTree: box.ergoTree, additionalRegisters: box.additionalRegisters, transactionId: box.transactionId, - index: box.index, + index: box.index }; }); @@ -84,8 +108,8 @@ The Box Data gotten from this API has some extra fields that we need to take out .from(boxes) .to( new OutputBuilder( - '100000000', - '9efPWBBjL1pddkH9pxnEjjGZxABseEjeXAAMxMUSV7Ug6nN44Wr' + "100000000", + "9efPWBBjL1pddkH9pxnEjjGZxABseEjeXAAMxMUSV7Ug6nN44Wr" ) ) .sendChangeTo(await ergo.get_change_address()) From 3168c2cb61b2920206ed3533398268fb181e2f93 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Mon, 22 Jul 2024 17:29:49 +0100 Subject: [PATCH 3/3] fix: page title for retrieve box --- docs/retrieving-boxes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/retrieving-boxes.md b/docs/retrieving-boxes.md index 6a0e676..d390b75 100644 --- a/docs/retrieving-boxes.md +++ b/docs/retrieving-boxes.md @@ -1,4 +1,4 @@ -# Retrieve and Use Boxes +# Retrieve and Utilize Boxes from Blockchain. When using the `TransactionBuilder` class, you will need to work with boxes, which are the fundamental building blocks of Ergo transactions. Boxes represent unspent transaction outputs (UTXOs) on the Ergo blockchain. Each box contains assets (such as ERG or tokens) and potentially additional data. @@ -88,7 +88,7 @@ The Box Data gotten from this API has some extra fields that we need to take out const _boxes = await fetchUnspentBoxesByAddress( await ergo.get_change_address() ); - // const _boxes = await fetchUnspentBoxesByAddress( + // const _boxes = await fetchUnspentBoxesByTokenId( // "f60bff91f7ae3f3a5f0c2d35b46ef8991f213a61d7f7e453d344fa52a42d9f9a" // SigUSD Token ID // ); const boxes = _boxes.map((box) => {