From 81640c450019254788211c28cb195f65891b02e8 Mon Sep 17 00:00:00 2001 From: maayan Date: Mon, 25 Mar 2024 11:35:35 -0400 Subject: [PATCH] calculate object address and token address --- CHANGELOG.md | 2 ++ src/core/account/index.ts | 1 + src/core/account/utils/address.ts | 39 ++++++++++++++++++++++++++++++ src/core/account/utils/index.ts | 1 + tests/unit/address.test.ts | 40 +++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 src/core/account/utils/address.ts create mode 100644 src/core/account/utils/index.ts create mode 100644 tests/unit/address.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index ebc579064..2640eafce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T - Add support to allow setting per-backend (fullnode, indexer, faucet) configuration - [`Breaking`] `AUTH_TOKEN` client config moved to be under `faucetConfig` property - Handle `Unauthorized` server error +- Add function to create object address locally +- Add function to create token object address locally # 1.10.0 (2024-03-11) diff --git a/src/core/account/index.ts b/src/core/account/index.ts index 873149228..66ec96043 100644 --- a/src/core/account/index.ts +++ b/src/core/account/index.ts @@ -1,3 +1,4 @@ export * from "./Ed25519Account"; export * from "./Account"; export * from "./SingleKeyAccount"; +export * from "./utils"; diff --git a/src/core/account/utils/address.ts b/src/core/account/utils/address.ts new file mode 100644 index 000000000..841c5ec2d --- /dev/null +++ b/src/core/account/utils/address.ts @@ -0,0 +1,39 @@ +import { sha3_256 } from "@noble/hashes/sha3"; +import { AccountAddress } from "../../accountAddress"; +import { DeriveScheme } from "../../../types"; + +/** + * Creates an object address from creator address and seed + * + * @param creatorAddress The object creator account address + * @param seed The seed in either Uint8Array | string type + * + * @returns The object account address + */ +export const createObjectAddress = (creatorAddress: AccountAddress, seed: Uint8Array | string): AccountAddress => { + const creatorBytes = creatorAddress.bcsToBytes(); + + const seedBytes = typeof seed === "string" ? Buffer.from(seed, "utf8") : seed; + + const bytes = new Uint8Array([...creatorBytes, ...seedBytes, DeriveScheme.DeriveObjectAddressFromSeed]); + + return new AccountAddress(sha3_256(bytes)); +}; + +/** + * Creates a token object address from creator address, collection name and token name + * + * @param creatorAddress The token creator account address + * @param collectionName The collection name + * @param tokenName The token name + * + * @returns The token account address + */ +export const createTokenAddress = ( + creatorAddress: AccountAddress, + collectionName: string, + tokenName: string, +): AccountAddress => { + const seed = `${collectionName}::${tokenName}`; + return createObjectAddress(creatorAddress, seed); +}; diff --git a/src/core/account/utils/index.ts b/src/core/account/utils/index.ts new file mode 100644 index 000000000..ce667bbed --- /dev/null +++ b/src/core/account/utils/index.ts @@ -0,0 +1 @@ +export * from "./address"; diff --git a/tests/unit/address.test.ts b/tests/unit/address.test.ts new file mode 100644 index 000000000..6b10193a8 --- /dev/null +++ b/tests/unit/address.test.ts @@ -0,0 +1,40 @@ +/* eslint-disable max-len */ +import { AccountAddress } from "../../src"; +import { createTokenAddress, createObjectAddress } from "../../src/core/account/utils/address"; + +describe("address", () => { + /** + * Reference: {@link https://explorer.aptoslabs.com/account/0xf0995d360365587c500cc171d1416bad10a331b9c71871a1aec5f2c37ff43124/modules/view/migration_helper/migration_object_address?network=testnet} + * creatorAddr = 0x120e79e45d21ef439963580c77a023e2729db799e96e61f878fac98fde5b9cc9 + * seed = "migration::migration_contract" + * Expect = 0xbe376272a5c4361ee96bc147525b26b3bf2ee25f433cbd410a7b3b4b881ffcbf + */ + test("create an object address from creator address and seed as Uint8Array type", () => { + const creatorAddress = AccountAddress.from("0x120e79e45d21ef439963580c77a023e2729db799e96e61f878fac98fde5b9cc9"); + const seed = Buffer.from("migration::migration_contract", "utf8"); + const address = createObjectAddress(creatorAddress, seed); + expect(address.toString()).toEqual("0xbe376272a5c4361ee96bc147525b26b3bf2ee25f433cbd410a7b3b4b881ffcbf"); + }); + + test("create an object address from creator address and seed as string type", () => { + const creatorAddress = AccountAddress.from("0x120e79e45d21ef439963580c77a023e2729db799e96e61f878fac98fde5b9cc9"); + const seed = "migration::migration_contract"; + const address = createObjectAddress(creatorAddress, seed); + expect(address.toString()).toEqual("0xbe376272a5c4361ee96bc147525b26b3bf2ee25f433cbd410a7b3b4b881ffcbf"); + }); + + /** + * Reference: {@link https://explorer.aptoslabs.com/txn/473081244/userTxnOverview?network=mainnet} + * creatorAddr = 0x9d518b9b84f327eafc5f6632200ea224a818a935ffd6be5d78ada250bbc44a6 + * collectionName = SuperV Villains + * tokenName = Nami #5962 + * Expect = 0x44697f48d1e1a899953b4ea6c03a92c567f3741f0b415a74d1c23cdf141368be + */ + test("create token object address", () => { + const creatorAddress = AccountAddress.from("0x9d518b9b84f327eafc5f6632200ea224a818a935ffd6be5d78ada250bbc44a6"); + const collectionName = "SuperV Villains"; + const tokenName = "Nami #5962"; + const address = createTokenAddress(creatorAddress, collectionName, tokenName); + expect(address.toString()).toEqual("0x44697f48d1e1a899953b4ea6c03a92c567f3741f0b415a74d1c23cdf141368be"); + }); +});