@sign-global/tokentable-core 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @sign-global/tokentable-core
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: update Arbitrum chain configuration
8
+
9
+ ## 0.0.0-beta-20250625021659
10
+
11
+ ### Major Changes
12
+
13
+ - ✨ feat: add beta version script and improve claim fee calculation
14
+
15
+ ## 0.0.0-beta-20250624084326
16
+
17
+ ### Minor Changes
18
+
19
+ - ✨ feat: add fee handling for TokenTableMerkleDistributorWithFees
20
+
3
21
  ## 1.0.0
4
22
 
5
23
  ### Major Changes
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # TokenTable Core Package
2
+
3
+ Core utilities and functions for the TokenTable SDK.
4
+
5
+ ## Development
6
+
7
+ ### Testing
8
+
9
+ This package uses [Vitest](https://vitest.dev/) for testing.
10
+
11
+ #### Running Tests
12
+
13
+ ```bash
14
+ # Run tests once
15
+ pnpm test:run
16
+
17
+ # Run tests in watch mode
18
+ pnpm test
19
+
20
+ # Run tests with UI
21
+ pnpm vitest --ui
22
+ ```
23
+
24
+ #### Test Structure
25
+
26
+ Tests are located in `src/**/__tests__/` directories following the pattern `*.test.ts`.
27
+
28
+ #### Current Test Coverage
29
+
30
+ - `getOrCreateAssociatedTokenAccount` - Comprehensive tests for Solana associated token account creation
31
+ - Tests existing account retrieval
32
+ - Tests new account creation when account doesn't exist
33
+ - Tests error handling for invalid mint/owner
34
+ - Tests custom parameter handling
35
+ - Tests unexpected error propagation
36
+
37
+ ### Building
38
+
39
+ ```bash
40
+ # Build the package
41
+ pnpm build
42
+
43
+ # Build in watch mode
44
+ pnpm build:watch
45
+ ```
46
+
47
+ ### Cleaning
48
+
49
+ ```bash
50
+ # Clean build artifacts
51
+ pnpm clean
52
+ ```
53
+
54
+ ## Testing Philosophy
55
+
56
+ The tests use comprehensive mocking to isolate the unit under test while ensuring all code paths are covered. Key testing principles:
57
+
58
+ 1. **Isolation**: External dependencies are mocked to focus on the function logic
59
+ 2. **Coverage**: All branches and error conditions are tested
60
+ 3. **Realistic Data**: Valid Solana public keys and realistic mock data are used
61
+ 4. **Error Handling**: Both expected and unexpected errors are tested
62
+
63
+ ## Dependencies
64
+
65
+ This package depends on:
66
+ - `@solana/web3.js` - Solana blockchain interaction
67
+ - `@solana/spl-token` - SPL Token program utilities
68
+ - Various other blockchain and utility libraries
69
+
70
+ Dev dependencies include:
71
+ - `vitest` - Testing framework
72
+ - `jsdom` - DOM environment for tests
package/dist/index.d.mts CHANGED
@@ -74,7 +74,7 @@ declare const ChainConfig: {
74
74
  };
75
75
  42161: {
76
76
  contractAddress: string;
77
- rpcUrl: "https://arb1.arbitrum.io/rpc";
77
+ rpcUrl: string;
78
78
  };
79
79
  80085: {
80
80
  contractAddress: string;
@@ -1803,6 +1803,7 @@ type IAirdropClaim = {
1803
1803
  data: string;
1804
1804
  leaf: string;
1805
1805
  claimed?: boolean;
1806
+ fees: string;
1806
1807
  claimId?: string;
1807
1808
  claimable?: boolean;
1808
1809
  proofHash: string;
@@ -1812,9 +1813,13 @@ type IAirdropClaim = {
1812
1813
  expired?: boolean;
1813
1814
  project: IProject;
1814
1815
  };
1816
+ interface IExtraData {
1817
+ isLegacy: boolean;
1818
+ attestationId: bigint;
1819
+ }
1815
1820
  interface IAirdropClaimData extends IAirdropClaim {
1816
- extraData: any;
1817
- value: bigint;
1821
+ extraData?: IExtraData;
1822
+ value?: bigint | string;
1818
1823
  }
1819
1824
  type IAirdropSignatureClaim = {
1820
1825
  percent: number;
@@ -2052,7 +2057,7 @@ declare function fetchTokenVersion(tokenAddress: string, options: FetchTokenMeta
2052
2057
  declare const clusterApiUrl: (cluster?: Cluster) => string;
2053
2058
 
2054
2059
  declare const getCustomNaNoId: () => string;
2055
- declare const safeParseJSON: (str: string) => any;
2060
+ declare const safeParseJSON: <T = any>(str: string | null | undefined, defaultValue?: T) => T;
2056
2061
  declare const isBeforeByUnix: (unix: number) => boolean;
2057
2062
  declare const delay: (ms: number) => Promise<unknown>;
2058
2063
  declare function retry<T>(fn: () => Promise<T>, options: {
@@ -2101,4 +2106,4 @@ declare const getAvailableClaimAmountForSignature: ({ contractAddress, chainId,
2101
2106
  }[];
2102
2107
  }) => Promise<string | 0>;
2103
2108
 
2104
- export { AirdropSigIdentityTypeEnum, ApiClient, type ApiClientOptions, type ApiRequestOptions, CONST, ChainConfig, type ChainId, ChainType, ETokenType, ErrorCode, AirdropService$2 as EvmAirdropService, EvmAirdropVersionEnum, type EvmContractClientOption, SignatureAirdropService$1 as EvmSignatureAirdropService, type FetchTokenMetadataOptions, type FetchTokenVersionOptions, type IAirdropClaim, type IAirdropClaimData, type IAirdropData, type IAirdropOptions, type IAirdropService, type IAirdropSignatureClaim, type IAirdropSignatureData, type IAirdropSignatureIdentity, type IClaimSignature, type IContractConfig, type IProject, type IProjectExtra, type IWalletClient, type Identity, AirdropService$1 as SolanaAirdropService, SignatureAirdropService as SolanaSignatureAirdropService, SplTokenVersion, type SupportedChainType, SupportedChains, type ThemeConfig, AirdropService as TonAirdropService, TonAirdropVersionEnum, TonWalletService, ZERO_ADDRESS, apiClient, batchCheckClaimedForSignature, bindWallet, checkEligibility, checkGetSignatures, cleanUrlParams, clusterApiUrl, connectGoogleApi, connectTwitter, delay, disconnectRecipient, fetchTokenVersion, flipAddressType, getAirdropContractConfig, getAirdropPro, getAirdropProject, getAirdropProjectId, getAirdropQuery, getAvailableClaimAmountForSignature, getChainById, getChainConfig, getChainRpc, getCustomNaNoId, getJettonInfo, getOrCreateAssociatedTokenAccount, getTonProjectIdByAddress, hexStrToU8Array, isBeforeByUnix, isGreaterThan, isMobile, mevmDevNet, retry, safeParseJSON, safePlus, signBrBTestnet, solanaDevNet, solanaMainNet, tonMainNet, tonTestNet };
2109
+ export { AirdropSigIdentityTypeEnum, ApiClient, type ApiClientOptions, type ApiRequestOptions, CONST, ChainConfig, type ChainId, ChainType, ETokenType, ErrorCode, AirdropService$2 as EvmAirdropService, EvmAirdropVersionEnum, type EvmContractClientOption, SignatureAirdropService$1 as EvmSignatureAirdropService, type FetchTokenMetadataOptions, type FetchTokenVersionOptions, type IAirdropClaim, type IAirdropClaimData, type IAirdropData, type IAirdropOptions, type IAirdropService, type IAirdropSignatureClaim, type IAirdropSignatureData, type IAirdropSignatureIdentity, type IClaimSignature, type IContractConfig, type IExtraData, type IProject, type IProjectExtra, type IWalletClient, type Identity, AirdropService$1 as SolanaAirdropService, SignatureAirdropService as SolanaSignatureAirdropService, SplTokenVersion, type SupportedChainType, SupportedChains, type ThemeConfig, AirdropService as TonAirdropService, TonAirdropVersionEnum, TonWalletService, ZERO_ADDRESS, apiClient, batchCheckClaimedForSignature, bindWallet, checkEligibility, checkGetSignatures, cleanUrlParams, clusterApiUrl, connectGoogleApi, connectTwitter, delay, disconnectRecipient, fetchTokenVersion, flipAddressType, getAirdropContractConfig, getAirdropPro, getAirdropProject, getAirdropProjectId, getAirdropQuery, getAvailableClaimAmountForSignature, getChainById, getChainConfig, getChainRpc, getCustomNaNoId, getJettonInfo, getOrCreateAssociatedTokenAccount, getTonProjectIdByAddress, hexStrToU8Array, isBeforeByUnix, isGreaterThan, isMobile, mevmDevNet, retry, safeParseJSON, safePlus, signBrBTestnet, solanaDevNet, solanaMainNet, tonMainNet, tonTestNet };
package/dist/index.d.ts CHANGED
@@ -74,7 +74,7 @@ declare const ChainConfig: {
74
74
  };
75
75
  42161: {
76
76
  contractAddress: string;
77
- rpcUrl: "https://arb1.arbitrum.io/rpc";
77
+ rpcUrl: string;
78
78
  };
79
79
  80085: {
80
80
  contractAddress: string;
@@ -1803,6 +1803,7 @@ type IAirdropClaim = {
1803
1803
  data: string;
1804
1804
  leaf: string;
1805
1805
  claimed?: boolean;
1806
+ fees: string;
1806
1807
  claimId?: string;
1807
1808
  claimable?: boolean;
1808
1809
  proofHash: string;
@@ -1812,9 +1813,13 @@ type IAirdropClaim = {
1812
1813
  expired?: boolean;
1813
1814
  project: IProject;
1814
1815
  };
1816
+ interface IExtraData {
1817
+ isLegacy: boolean;
1818
+ attestationId: bigint;
1819
+ }
1815
1820
  interface IAirdropClaimData extends IAirdropClaim {
1816
- extraData: any;
1817
- value: bigint;
1821
+ extraData?: IExtraData;
1822
+ value?: bigint | string;
1818
1823
  }
1819
1824
  type IAirdropSignatureClaim = {
1820
1825
  percent: number;
@@ -2052,7 +2057,7 @@ declare function fetchTokenVersion(tokenAddress: string, options: FetchTokenMeta
2052
2057
  declare const clusterApiUrl: (cluster?: Cluster) => string;
2053
2058
 
2054
2059
  declare const getCustomNaNoId: () => string;
2055
- declare const safeParseJSON: (str: string) => any;
2060
+ declare const safeParseJSON: <T = any>(str: string | null | undefined, defaultValue?: T) => T;
2056
2061
  declare const isBeforeByUnix: (unix: number) => boolean;
2057
2062
  declare const delay: (ms: number) => Promise<unknown>;
2058
2063
  declare function retry<T>(fn: () => Promise<T>, options: {
@@ -2101,4 +2106,4 @@ declare const getAvailableClaimAmountForSignature: ({ contractAddress, chainId,
2101
2106
  }[];
2102
2107
  }) => Promise<string | 0>;
2103
2108
 
2104
- export { AirdropSigIdentityTypeEnum, ApiClient, type ApiClientOptions, type ApiRequestOptions, CONST, ChainConfig, type ChainId, ChainType, ETokenType, ErrorCode, AirdropService$2 as EvmAirdropService, EvmAirdropVersionEnum, type EvmContractClientOption, SignatureAirdropService$1 as EvmSignatureAirdropService, type FetchTokenMetadataOptions, type FetchTokenVersionOptions, type IAirdropClaim, type IAirdropClaimData, type IAirdropData, type IAirdropOptions, type IAirdropService, type IAirdropSignatureClaim, type IAirdropSignatureData, type IAirdropSignatureIdentity, type IClaimSignature, type IContractConfig, type IProject, type IProjectExtra, type IWalletClient, type Identity, AirdropService$1 as SolanaAirdropService, SignatureAirdropService as SolanaSignatureAirdropService, SplTokenVersion, type SupportedChainType, SupportedChains, type ThemeConfig, AirdropService as TonAirdropService, TonAirdropVersionEnum, TonWalletService, ZERO_ADDRESS, apiClient, batchCheckClaimedForSignature, bindWallet, checkEligibility, checkGetSignatures, cleanUrlParams, clusterApiUrl, connectGoogleApi, connectTwitter, delay, disconnectRecipient, fetchTokenVersion, flipAddressType, getAirdropContractConfig, getAirdropPro, getAirdropProject, getAirdropProjectId, getAirdropQuery, getAvailableClaimAmountForSignature, getChainById, getChainConfig, getChainRpc, getCustomNaNoId, getJettonInfo, getOrCreateAssociatedTokenAccount, getTonProjectIdByAddress, hexStrToU8Array, isBeforeByUnix, isGreaterThan, isMobile, mevmDevNet, retry, safeParseJSON, safePlus, signBrBTestnet, solanaDevNet, solanaMainNet, tonMainNet, tonTestNet };
2109
+ export { AirdropSigIdentityTypeEnum, ApiClient, type ApiClientOptions, type ApiRequestOptions, CONST, ChainConfig, type ChainId, ChainType, ETokenType, ErrorCode, AirdropService$2 as EvmAirdropService, EvmAirdropVersionEnum, type EvmContractClientOption, SignatureAirdropService$1 as EvmSignatureAirdropService, type FetchTokenMetadataOptions, type FetchTokenVersionOptions, type IAirdropClaim, type IAirdropClaimData, type IAirdropData, type IAirdropOptions, type IAirdropService, type IAirdropSignatureClaim, type IAirdropSignatureData, type IAirdropSignatureIdentity, type IClaimSignature, type IContractConfig, type IExtraData, type IProject, type IProjectExtra, type IWalletClient, type Identity, AirdropService$1 as SolanaAirdropService, SignatureAirdropService as SolanaSignatureAirdropService, SplTokenVersion, type SupportedChainType, SupportedChains, type ThemeConfig, AirdropService as TonAirdropService, TonAirdropVersionEnum, TonWalletService, ZERO_ADDRESS, apiClient, batchCheckClaimedForSignature, bindWallet, checkEligibility, checkGetSignatures, cleanUrlParams, clusterApiUrl, connectGoogleApi, connectTwitter, delay, disconnectRecipient, fetchTokenVersion, flipAddressType, getAirdropContractConfig, getAirdropPro, getAirdropProject, getAirdropProjectId, getAirdropQuery, getAvailableClaimAmountForSignature, getChainById, getChainConfig, getChainRpc, getCustomNaNoId, getJettonInfo, getOrCreateAssociatedTokenAccount, getTonProjectIdByAddress, hexStrToU8Array, isBeforeByUnix, isGreaterThan, isMobile, mevmDevNet, retry, safeParseJSON, safePlus, signBrBTestnet, solanaDevNet, solanaMainNet, tonMainNet, tonTestNet };
package/dist/index.js CHANGED
@@ -277,8 +277,8 @@ var ChainConfig = {
277
277
  rpcUrl: "https://zetachain-mainnet.g.alchemy.com/v2/1tmk0FrhwTJHXh0XIyae7_SXw1lDCjgs"
278
278
  },
279
279
  [import_chains.arbitrum.id]: {
280
- contractAddress: "0x759ac3CA33FeeAfB8C41aEbC8687A7Bd849Fc87a",
281
- rpcUrl: import_chains.arbitrum.rpcUrls.default.http[0]
280
+ contractAddress: "0xeD09c23677D02f4f486E55f0f081cfc114EEa53b",
281
+ rpcUrl: "https://arb-mainnet.g.alchemy.com/v2/udrqNPSB6i5n5L6QSM31Ng72h_hFOrVT"
282
282
  },
283
283
  [import_chains.berachainTestnet.id]: {
284
284
  contractAddress: "",
@@ -3899,11 +3899,16 @@ var getCustomNaNoId = () => {
3899
3899
  const nanoid = (0, import_nanoid.customAlphabet)("1234567890abcdefghijklmnopqrstuvwxyz", 10);
3900
3900
  return nanoid();
3901
3901
  };
3902
- var safeParseJSON = (str) => {
3902
+ var safeParseJSON = (str, defaultValue = {}) => {
3903
+ if (!str || typeof str !== "string") {
3904
+ return defaultValue;
3905
+ }
3903
3906
  try {
3904
- return JSON.parse(str);
3907
+ const parsed = JSON.parse(str);
3908
+ return parsed !== null && parsed !== void 0 ? parsed : defaultValue;
3905
3909
  } catch (error) {
3906
- return {};
3910
+ console.warn("Failed to parse JSON:", error);
3911
+ return defaultValue;
3907
3912
  }
3908
3913
  };
3909
3914
  var isBeforeByUnix = (unix) => {
@@ -3971,7 +3976,7 @@ var ApiClient = class _ApiClient {
3971
3976
  }
3972
3977
  const res = await fetch(finalUrl, init);
3973
3978
  const [status, resData] = await Promise.all([res.status, res.json()]);
3974
- if (status < 200 && status >= 300 || resData?.success !== true) {
3979
+ if (status < 200 || status >= 300 || resData?.success !== true) {
3975
3980
  return Promise.reject(resData);
3976
3981
  }
3977
3982
  return resData.data;
@@ -4150,22 +4155,27 @@ var AirdropService = class {
4150
4155
  return this.airdropV3FeeClient.getFeelessThreshold();
4151
4156
  }
4152
4157
  async getClaimFee(address, amount) {
4153
- const feeCollector = await this.feeCollectors(this.options.contractAddress);
4154
- if (!feeCollector || feeCollector === ZERO_ADDRESS) {
4155
- return void 0;
4156
- }
4157
- const feeClient = this.getFeeClient(feeCollector);
4158
- const fee = await feeClient.getFee(address, amount);
4159
- const version = await this.getVersion();
4160
- if (version === "0.3.0" /* V3 */) {
4161
- const threshold = await this.getFeelessThreshold();
4162
- if (isGreaterThan(Number(amount), Number(threshold))) {
4163
- return fee;
4164
- } else {
4158
+ try {
4159
+ const feeCollector = await this.feeCollectors(this.options.contractAddress);
4160
+ if (!feeCollector || feeCollector === ZERO_ADDRESS) {
4165
4161
  return void 0;
4166
4162
  }
4163
+ const feeClient = this.getFeeClient(feeCollector);
4164
+ const fee = await feeClient.getFee(address, amount);
4165
+ const version = await this.getVersion();
4166
+ if (version === "0.3.0" /* V3 */) {
4167
+ const threshold = await this.getFeelessThreshold();
4168
+ if (isGreaterThan(Number(amount), Number(threshold))) {
4169
+ return fee;
4170
+ } else {
4171
+ return void 0;
4172
+ }
4173
+ }
4174
+ return fee;
4175
+ } catch (error) {
4176
+ console.error("Failed to get claim fee:", error);
4177
+ throw new Error(`Failed to calculate claim fee: ${error instanceof Error ? error.message : "Unknown error"}`);
4167
4178
  }
4168
- return fee;
4169
4179
  }
4170
4180
  async getKycThreshold() {
4171
4181
  const kycClient = await this.getKycClient();
@@ -10480,7 +10490,9 @@ var createApiClient = (baseURL) => {
10480
10490
  var getAirdropProject = async (projectId, baseURL) => {
10481
10491
  const client = createApiClient(baseURL);
10482
10492
  const res = await client.get(`/airdrop-open/projects/${projectId}`);
10483
- if (!res) return res;
10493
+ if (!res) {
10494
+ throw new Error(`Project not found: ${projectId}`);
10495
+ }
10484
10496
  const projectConfig = res?.themeConf;
10485
10497
  const blockCountries = safeParseJSON(projectConfig?.blockCountries);
10486
10498
  return {