sdk/js: reconstruct TokenId obect in getForeignAssetAptos to reduce number of RPC calls

This commit is contained in:
heyitaki 2023-02-09 01:57:49 +00:00 committed by Evan Gray
parent e0bebed306
commit 1deee6f7a1
2 changed files with 64 additions and 45 deletions

View File

@ -507,6 +507,17 @@ describe("Aptos NFT SDK tests", () => {
);
expect(tokenId1.token_data_id.creator).toBe(tokenId2.token_data_id.creator);
expect(tokenId1.token_data_id.name).not.toBe(tokenId2.token_data_id.name);
// check if token that does not exist correctly returns null foreign asset address
expect(
await getForeignAssetAptos(
aptosClient,
APTOS_NFT_BRIDGE_ADDRESS,
CHAIN_ID_ETH,
tryNativeToUint8Array(ethNfts.address, CHAIN_ID_ETH),
BigInt(2)
)
).toBe(null);
});
});

View File

@ -1,12 +1,18 @@
import { BN } from "@project-serum/anchor";
import { PublicKeyInitData } from "@solana/web3.js";
import { LCDClient } from "@terra-money/terra.js";
import { AptosClient, HexString, TokenTypes, Types } from "aptos";
import {
ApiError,
AptosClient,
HexString,
TokenClient,
TokenTypes,
} from "aptos";
import { ethers } from "ethers";
import { isBytes } from "ethers/lib/utils";
import { fromUint8Array } from "js-base64";
import { CHAIN_ID_SOLANA } from "..";
import { CreateTokenDataEvent, NftBridgeState } from "../aptos/types";
import { CreateTokenDataEvent } from "../aptos/types";
import { NFTBridge__factory } from "../ethers-contracts";
import { deriveWrappedMintKey } from "../solana/nftBridge";
import {
@ -16,6 +22,7 @@ import {
coalesceChainId,
deriveResourceAccountAddress,
ensureHexPrefix,
getTokenIdFromTokenHash,
hexToUint8Array,
} from "../utils";
@ -135,24 +142,7 @@ export async function getForeignAssetAptos(
): Promise<TokenTypes.TokenId | null> {
const originChainId = coalesceChainId(originChain);
if (originChainId === CHAIN_ID_APTOS) {
const state = (
await client.getAccountResource(
nftBridgeAddress,
`${nftBridgeAddress}::state::State`
)
).data as NftBridgeState;
const handle = state.native_infos.handle;
const { token_data_id, property_version } = (await client.getTableItem(
handle,
{
key_type: `${nftBridgeAddress}::token_hash::TokenHash`,
value_type: `0x3::token::TokenId`,
key: {
hash: HexString.fromUint8Array(originAddress).hex(),
},
}
)) as TokenTypes.TokenId & { __headers: unknown };
return { token_data_id, property_version };
return getTokenIdFromTokenHash(client, nftBridgeAddress, originAddress);
}
const creatorAddress = await deriveResourceAccountAddress(
@ -175,33 +165,51 @@ export async function getForeignAssetAptos(
const tokenIdAsUint8Array = new Uint8Array(tokenId);
// Each creator account should contain a single collection that contains the
// token creation event with the token id that we're looking for.
// corresponding token creation events. Return if we find it in the first
// page, otherwise reconstruct the token id from the first event.
const PAGE_SIZE = 25;
let curr = 0;
let numEvents = PAGE_SIZE;
let event: Types.Event | undefined = undefined;
while (numEvents === PAGE_SIZE && !event) {
const events = await client.getEventsByEventHandle(
creatorAddress,
"0x3::token::Collections",
"create_token_data_events",
{ limit: PAGE_SIZE, start: curr }
);
event = events.find(
(e) =>
ensureHexPrefix((e as CreateTokenDataEvent).data.id.name) ===
HexString.fromUint8Array(tokenIdAsUint8Array).hex()
);
numEvents = events.length;
curr += numEvents;
const events = (await client.getEventsByEventHandle(
creatorAddress,
"0x3::token::Collections",
"create_token_data_events",
{ limit: PAGE_SIZE }
)) as CreateTokenDataEvent[];
const event = events.find(
(e) =>
ensureHexPrefix((e as CreateTokenDataEvent).data.id.name) ===
HexString.fromUint8Array(tokenIdAsUint8Array).hex()
);
if (event) {
return {
token_data_id: event.data.id,
property_version: "0", // property version always "0" for wrapped tokens
};
}
if (!event) {
throw new Error("Invalid token ID");
}
// Skip pagination, reconstruct token id, and check to see if it exists
try {
const tokenIdObj = {
token_data_id: {
...events[0].data.id,
name: HexString.fromUint8Array(tokenIdAsUint8Array).noPrefix(),
},
property_version: "0",
};
await new TokenClient(client).getTokenData(
tokenIdObj.token_data_id.creator,
tokenIdObj.token_data_id.collection,
tokenIdObj.token_data_id.name
);
return tokenIdObj;
} catch (e) {
if (
e instanceof ApiError &&
e.status === 404 &&
e.errorCode === "table_item_not_found"
) {
return null;
}
return {
token_data_id: event.data.id,
property_version: "0",
};
throw e;
}
}