sdk/js: reconstruct TokenId obect in getForeignAssetAptos to reduce number of RPC calls
This commit is contained in:
parent
e0bebed306
commit
1deee6f7a1
|
@ -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.creator).toBe(tokenId2.token_data_id.creator);
|
||||||
expect(tokenId1.token_data_id.name).not.toBe(tokenId2.token_data_id.name);
|
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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
import { BN } from "@project-serum/anchor";
|
import { BN } from "@project-serum/anchor";
|
||||||
import { PublicKeyInitData } from "@solana/web3.js";
|
import { PublicKeyInitData } from "@solana/web3.js";
|
||||||
import { LCDClient } from "@terra-money/terra.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 { ethers } from "ethers";
|
||||||
import { isBytes } from "ethers/lib/utils";
|
import { isBytes } from "ethers/lib/utils";
|
||||||
import { fromUint8Array } from "js-base64";
|
import { fromUint8Array } from "js-base64";
|
||||||
import { CHAIN_ID_SOLANA } from "..";
|
import { CHAIN_ID_SOLANA } from "..";
|
||||||
import { CreateTokenDataEvent, NftBridgeState } from "../aptos/types";
|
import { CreateTokenDataEvent } from "../aptos/types";
|
||||||
import { NFTBridge__factory } from "../ethers-contracts";
|
import { NFTBridge__factory } from "../ethers-contracts";
|
||||||
import { deriveWrappedMintKey } from "../solana/nftBridge";
|
import { deriveWrappedMintKey } from "../solana/nftBridge";
|
||||||
import {
|
import {
|
||||||
|
@ -16,6 +22,7 @@ import {
|
||||||
coalesceChainId,
|
coalesceChainId,
|
||||||
deriveResourceAccountAddress,
|
deriveResourceAccountAddress,
|
||||||
ensureHexPrefix,
|
ensureHexPrefix,
|
||||||
|
getTokenIdFromTokenHash,
|
||||||
hexToUint8Array,
|
hexToUint8Array,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
|
@ -135,24 +142,7 @@ export async function getForeignAssetAptos(
|
||||||
): Promise<TokenTypes.TokenId | null> {
|
): Promise<TokenTypes.TokenId | null> {
|
||||||
const originChainId = coalesceChainId(originChain);
|
const originChainId = coalesceChainId(originChain);
|
||||||
if (originChainId === CHAIN_ID_APTOS) {
|
if (originChainId === CHAIN_ID_APTOS) {
|
||||||
const state = (
|
return getTokenIdFromTokenHash(client, nftBridgeAddress, originAddress);
|
||||||
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 };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const creatorAddress = await deriveResourceAccountAddress(
|
const creatorAddress = await deriveResourceAccountAddress(
|
||||||
|
@ -175,33 +165,51 @@ export async function getForeignAssetAptos(
|
||||||
const tokenIdAsUint8Array = new Uint8Array(tokenId);
|
const tokenIdAsUint8Array = new Uint8Array(tokenId);
|
||||||
|
|
||||||
// Each creator account should contain a single collection that contains the
|
// 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;
|
const PAGE_SIZE = 25;
|
||||||
let curr = 0;
|
const events = (await client.getEventsByEventHandle(
|
||||||
let numEvents = PAGE_SIZE;
|
creatorAddress,
|
||||||
let event: Types.Event | undefined = undefined;
|
"0x3::token::Collections",
|
||||||
while (numEvents === PAGE_SIZE && !event) {
|
"create_token_data_events",
|
||||||
const events = await client.getEventsByEventHandle(
|
{ limit: PAGE_SIZE }
|
||||||
creatorAddress,
|
)) as CreateTokenDataEvent[];
|
||||||
"0x3::token::Collections",
|
const event = events.find(
|
||||||
"create_token_data_events",
|
(e) =>
|
||||||
{ limit: PAGE_SIZE, start: curr }
|
ensureHexPrefix((e as CreateTokenDataEvent).data.id.name) ===
|
||||||
);
|
HexString.fromUint8Array(tokenIdAsUint8Array).hex()
|
||||||
event = events.find(
|
);
|
||||||
(e) =>
|
if (event) {
|
||||||
ensureHexPrefix((e as CreateTokenDataEvent).data.id.name) ===
|
return {
|
||||||
HexString.fromUint8Array(tokenIdAsUint8Array).hex()
|
token_data_id: event.data.id,
|
||||||
);
|
property_version: "0", // property version always "0" for wrapped tokens
|
||||||
numEvents = events.length;
|
};
|
||||||
curr += numEvents;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!event) {
|
// Skip pagination, reconstruct token id, and check to see if it exists
|
||||||
throw new Error("Invalid token ID");
|
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 {
|
throw e;
|
||||||
token_data_id: event.data.id,
|
}
|
||||||
property_version: "0",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue