sdk/aptos: use qualified type instead of module address

This commit is contained in:
aki 2022-10-25 15:02:04 +00:00 committed by Evan Gray
parent 027354f319
commit a54030b6ed
7 changed files with 46 additions and 32 deletions

View File

@ -1,5 +1,11 @@
# Changelog # Changelog
## 0.9.0
### Changed
Use FQTs in Aptos SDK
## 0.8.0 ## 0.8.0
### Added ### Added

View File

@ -1,6 +1,6 @@
{ {
"name": "@certusone/wormhole-sdk", "name": "@certusone/wormhole-sdk",
"version": "0.8.0", "version": "0.9.0",
"description": "SDK for interacting with Wormhole", "description": "SDK for interacting with Wormhole",
"homepage": "https://wormhole.com", "homepage": "https://wormhole.com",
"main": "./lib/cjs/index.js", "main": "./lib/cjs/index.js",

View File

@ -291,29 +291,20 @@ describe("Aptos SDK tests", () => {
} }
// check attestation on aptos // check attestation on aptos
const aptosWrappedAddress = await getForeignAssetAptos( const aptosWrappedType = await getForeignAssetAptos(
client, client,
aptosTokenBridge, aptosTokenBridge,
CHAIN_ID_ETH, CHAIN_ID_ETH,
TEST_ERC20 TEST_ERC20
); );
if (!aptosWrappedAddress) { if (!aptosWrappedType) {
throw new Error("Failed to create wrapped coin on Aptos"); throw new Error("Failed to create wrapped coin on Aptos");
} }
const wrappedType = getAssetFullyQualifiedType(
aptosTokenBridge,
CHAIN_ID_ETH,
TEST_ERC20
);
if (!wrappedType) {
throw new Error("wrappedType is null");
}
const info = await getOriginalAssetAptos( const info = await getOriginalAssetAptos(
client, client,
aptosTokenBridge, aptosTokenBridge,
wrappedType aptosWrappedType
); );
expect(uint8ArrayToHex(info.assetAddress)).toEqual( expect(uint8ArrayToHex(info.assetAddress)).toEqual(
tryNativeToHexString(TEST_ERC20, CHAIN_ID_ETH) tryNativeToHexString(TEST_ERC20, CHAIN_ID_ETH)
@ -323,7 +314,7 @@ describe("Aptos SDK tests", () => {
await getIsWrappedAssetAptos( await getIsWrappedAssetAptos(
client, client,
aptosTokenBridge, aptosTokenBridge,
aptosWrappedAddress aptosWrappedType
) )
); );
@ -363,7 +354,7 @@ describe("Aptos SDK tests", () => {
// redeem on aptos // redeem on aptos
const balanceBeforeTransferAptos = ethers.BigNumber.from( const balanceBeforeTransferAptos = ethers.BigNumber.from(
await getBalanceAptos(client, wrappedType, recipient.address()) await getBalanceAptos(client, aptosWrappedType, recipient.address())
); );
const redeemPayload = await redeemOnAptos( const redeemPayload = await redeemOnAptos(
client, client,
@ -377,7 +368,7 @@ describe("Aptos SDK tests", () => {
// check balances // check balances
const balanceAfterTransferAptos = ethers.BigNumber.from( const balanceAfterTransferAptos = ethers.BigNumber.from(
await getBalanceAptos(client, wrappedType, recipient.address()) await getBalanceAptos(client, aptosWrappedType, recipient.address())
); );
expect( expect(
balanceAfterTransferAptos.sub(balanceBeforeTransferAptos).toString() balanceAfterTransferAptos.sub(balanceBeforeTransferAptos).toString()

View File

@ -14,8 +14,8 @@ import {
ChainName, ChainName,
CHAIN_ID_ALGORAND, CHAIN_ID_ALGORAND,
coalesceChainId, coalesceChainId,
ensureHexPrefix, getAssetFullyQualifiedType,
getForeignAssetAddress, coalesceModuleAddress,
} from "../utils"; } from "../utils";
import { Provider } from "near-api-js/lib/providers"; import { Provider } from "near-api-js/lib/providers";
import { LCDClient as XplaLCDClient } from "@xpla/xpla.js"; import { LCDClient as XplaLCDClient } from "@xpla/xpla.js";
@ -192,12 +192,12 @@ export async function getForeignAssetNear(
} }
/** /**
* Get native module address of asset given its origin info. * Get qualified type of asset on Aptos given its origin info.
* @param client Client used to transfer data to/from Aptos node * @param client Client used to transfer data to/from Aptos node
* @param tokenBridgeAddress Address of token bridge * @param tokenBridgeAddress Address of token bridge
* @param originChain Chain ID of chain asset is originally from * @param originChain Chain ID of chain asset is originally from
* @param originAddress Asset address on origin chain * @param originAddress Asset address on origin chain
* @returns Asset module address on Aptos * @returns Fully qualified type of asset on Aptos
*/ */
export async function getForeignAssetAptos( export async function getForeignAssetAptos(
client: AptosClient, client: AptosClient,
@ -206,22 +206,22 @@ export async function getForeignAssetAptos(
originAddress: string originAddress: string
): Promise<string | null> { ): Promise<string | null> {
const originChainId = coalesceChainId(originChain); const originChainId = coalesceChainId(originChain);
const assetAddress = getForeignAssetAddress( const assetFullyQualifiedType = getAssetFullyQualifiedType(
tokenBridgeAddress, tokenBridgeAddress,
originChainId, originChainId,
originAddress originAddress
); );
if (!assetAddress) { if (!assetFullyQualifiedType) {
return null; return null;
} }
try { try {
// check if asset exists and throw if it doesn't // check if asset exists and throw if it doesn't
await client.getAccountResource( await client.getAccountResource(
assetAddress, coalesceModuleAddress(assetFullyQualifiedType),
`0x1::coin::CoinInfo<${ensureHexPrefix(assetAddress)}::coin::T>` `0x1::coin::CoinInfo<${assetFullyQualifiedType}>`
); );
return assetAddress; return assetFullyQualifiedType;
} catch (e) { } catch (e) {
return null; return null;
} }

View File

@ -6,7 +6,12 @@ import { AptosClient } from "aptos";
import { ethers } from "ethers"; import { ethers } from "ethers";
import { Bridge__factory } from "../ethers-contracts"; import { Bridge__factory } from "../ethers-contracts";
import { importTokenWasm } from "../solana/wasm"; import { importTokenWasm } from "../solana/wasm";
import { CHAIN_ID_INJECTIVE, ensureHexPrefix, tryNativeToHexString } from "../utils"; import {
CHAIN_ID_INJECTIVE,
ensureHexPrefix,
coalesceModuleAddress,
tryNativeToHexString,
} from "../utils";
import { safeBigIntToNumber } from "../utils/bigint"; import { safeBigIntToNumber } from "../utils/bigint";
import { getForeignAssetInjective } from "./getForeignAsset"; import { getForeignAssetInjective } from "./getForeignAsset";
@ -120,18 +125,21 @@ export function getIsWrappedAssetNear(
* Determines whether or not given address is wrapped or native to Aptos. * Determines whether or not given address is wrapped or native to Aptos.
* @param client Client used to transfer data to/from Aptos node * @param client Client used to transfer data to/from Aptos node
* @param tokenBridgeAddress Address of token bridge * @param tokenBridgeAddress Address of token bridge
* @param assetAddress Module address of asset * @param assetFullyQualifiedType Fully qualified type of asset
* @returns True if asset is wrapped * @returns True if asset is wrapped
*/ */
export async function getIsWrappedAssetAptos( export async function getIsWrappedAssetAptos(
client: AptosClient, client: AptosClient,
tokenBridgeAddress: string, tokenBridgeAddress: string,
assetAddress: string, assetFullyQualifiedType: string
): Promise<boolean> { ): Promise<boolean> {
assetAddress = ensureHexPrefix(assetAddress); assetFullyQualifiedType = ensureHexPrefix(assetFullyQualifiedType);
try { try {
// get origin info from asset address // get origin info from asset address
await client.getAccountResource(assetAddress, `${tokenBridgeAddress}::state::OriginInfo`); await client.getAccountResource(
coalesceModuleAddress(assetFullyQualifiedType),
`${tokenBridgeAddress}::state::OriginInfo`
);
return true; return true;
} catch { } catch {
return false; return false;

View File

@ -326,7 +326,7 @@ export async function getOriginalAssetAptos(
fullyQualifiedType: string fullyQualifiedType: string
): Promise<WormholeWrappedInfo> { ): Promise<WormholeWrappedInfo> {
if (!isValidAptosType(fullyQualifiedType)) { if (!isValidAptosType(fullyQualifiedType)) {
throw new Error("Need fully qualified address"); throw new Error("Invalid qualified type");
} }
let originInfo: OriginInfo | undefined; let originInfo: OriginInfo | undefined;

View File

@ -109,7 +109,7 @@ export const getAssetFullyQualifiedType = (
if (originChain === CHAIN_ID_APTOS) { if (originChain === CHAIN_ID_APTOS) {
// originAddress should be of form address::module::type // originAddress should be of form address::module::type
if (!isValidAptosType(originAddress)) { if (!isValidAptosType(originAddress)) {
console.error("Need fully qualified address for native asset"); console.error("Invalid qualified type");
return null; return null;
} }
@ -230,6 +230,15 @@ export async function getTypeFromExternalAddress(
} }
} }
/**
* Returns module address from given fully qualified type/module address.
* @param str FQT or module address
* @returns Module address
*/
export const coalesceModuleAddress = (str: string): string => {
return str.split("::")[0];
};
/** /**
* Simulates given raw transaction and either returns the resulting transaction that was submitted * Simulates given raw transaction and either returns the resulting transaction that was submitted
* to the mempool, or throws if it fails. * to the mempool, or throws if it fails.