@sign-global/tokentable 0.0.5 → 0.0.6

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.
Files changed (54) hide show
  1. package/dist/cjs/airdrop/index.d.ts +10 -12
  2. package/dist/cjs/airdrop/index.js +115 -110
  3. package/dist/cjs/airdrop/index.js.map +1 -1
  4. package/dist/cjs/airdrop/services/index.d.ts +6 -1
  5. package/dist/cjs/airdrop/services/index.js +6 -1
  6. package/dist/cjs/airdrop/services/index.js.map +1 -1
  7. package/dist/cjs/airdrop/strategies/AirdropStrategyFactory.d.ts +13 -0
  8. package/dist/cjs/airdrop/strategies/AirdropStrategyFactory.js +22 -0
  9. package/dist/cjs/airdrop/strategies/AirdropStrategyFactory.js.map +1 -0
  10. package/dist/cjs/airdrop/strategies/EvmAirdropStrategy.d.ts +26 -0
  11. package/dist/cjs/airdrop/strategies/EvmAirdropStrategy.js +79 -0
  12. package/dist/cjs/airdrop/strategies/EvmAirdropStrategy.js.map +1 -0
  13. package/dist/cjs/airdrop/strategies/IAirdropStrategy.d.ts +27 -0
  14. package/dist/cjs/airdrop/strategies/IAirdropStrategy.js +3 -0
  15. package/dist/cjs/airdrop/strategies/IAirdropStrategy.js.map +1 -0
  16. package/dist/cjs/airdrop/strategies/StrategyCache.d.ts +10 -0
  17. package/dist/cjs/airdrop/strategies/StrategyCache.js +32 -0
  18. package/dist/cjs/airdrop/strategies/StrategyCache.js.map +1 -0
  19. package/dist/cjs/airdrop/strategies/TonAirdropStrategy.d.ts +26 -0
  20. package/dist/cjs/airdrop/strategies/TonAirdropStrategy.js +64 -0
  21. package/dist/cjs/airdrop/strategies/TonAirdropStrategy.js.map +1 -0
  22. package/dist/cjs/airdrop/types/index.d.ts +5 -0
  23. package/dist/esm/airdrop/index.d.ts +10 -12
  24. package/dist/esm/airdrop/index.js +117 -112
  25. package/dist/esm/airdrop/index.js.map +1 -1
  26. package/dist/esm/airdrop/services/index.d.ts +6 -1
  27. package/dist/esm/airdrop/services/index.js +4 -0
  28. package/dist/esm/airdrop/services/index.js.map +1 -1
  29. package/dist/esm/airdrop/strategies/AirdropStrategyFactory.d.ts +13 -0
  30. package/dist/esm/airdrop/strategies/AirdropStrategyFactory.js +18 -0
  31. package/dist/esm/airdrop/strategies/AirdropStrategyFactory.js.map +1 -0
  32. package/dist/esm/airdrop/strategies/EvmAirdropStrategy.d.ts +26 -0
  33. package/dist/esm/airdrop/strategies/EvmAirdropStrategy.js +75 -0
  34. package/dist/esm/airdrop/strategies/EvmAirdropStrategy.js.map +1 -0
  35. package/dist/esm/airdrop/strategies/IAirdropStrategy.d.ts +27 -0
  36. package/dist/esm/airdrop/strategies/IAirdropStrategy.js +2 -0
  37. package/dist/esm/airdrop/strategies/IAirdropStrategy.js.map +1 -0
  38. package/dist/esm/airdrop/strategies/StrategyCache.d.ts +10 -0
  39. package/dist/esm/airdrop/strategies/StrategyCache.js +28 -0
  40. package/dist/esm/airdrop/strategies/StrategyCache.js.map +1 -0
  41. package/dist/esm/airdrop/strategies/TonAirdropStrategy.d.ts +26 -0
  42. package/dist/esm/airdrop/strategies/TonAirdropStrategy.js +60 -0
  43. package/dist/esm/airdrop/strategies/TonAirdropStrategy.js.map +1 -0
  44. package/dist/esm/airdrop/types/index.d.ts +5 -0
  45. package/package.json +1 -1
  46. package/src/airdrop/index.ts +140 -139
  47. package/src/airdrop/services/index.ts +6 -1
  48. package/src/airdrop/strategies/AirdropStrategyFactory.ts +29 -0
  49. package/src/airdrop/strategies/EvmAirdropStrategy.ts +85 -0
  50. package/src/airdrop/strategies/IAirdropStrategy.ts +25 -0
  51. package/src/airdrop/strategies/StrategyCache.ts +34 -0
  52. package/src/airdrop/strategies/TonAirdropStrategy.ts +72 -0
  53. package/src/airdrop/tests/index.test.ts +85 -0
  54. package/src/airdrop/types/index.ts +6 -0
@@ -0,0 +1,26 @@
1
+ import { IWalletClient } from '../types';
2
+ import { IAirdropStrategy } from './IAirdropStrategy';
3
+ export declare class EvmAirdropStrategy implements IAirdropStrategy {
4
+ private service;
5
+ private readonly contractAddress;
6
+ private readonly chainId;
7
+ private walletClient?;
8
+ private cachedVersion;
9
+ constructor(params: {
10
+ contractAddress: string;
11
+ chainId: string | number;
12
+ walletClient?: IWalletClient;
13
+ });
14
+ initialize(walletClient?: IWalletClient): Promise<void>;
15
+ isInitialized(): boolean;
16
+ getVersion(): Promise<string>;
17
+ claim(claimData: any): Promise<any>;
18
+ checkClaimed(claimData: any): Promise<boolean>;
19
+ batchCheckClaimed(leafs: string[]): Promise<{
20
+ result: boolean;
21
+ status: string;
22
+ }[]>;
23
+ getNFT(): Promise<string>;
24
+ getKycThreshold(): Promise<bigint>;
25
+ getClaimFee(contractAddress: string, amount: bigint): Promise<bigint>;
26
+ }
@@ -0,0 +1,75 @@
1
+ import { AirdropService as EvmAirdropService } from '../core/evm/AirdropService';
2
+ export class EvmAirdropStrategy {
3
+ service;
4
+ contractAddress;
5
+ chainId;
6
+ walletClient;
7
+ cachedVersion = null;
8
+ constructor(params) {
9
+ this.contractAddress = params.contractAddress;
10
+ this.chainId = Number(params.chainId);
11
+ if (params.walletClient) {
12
+ this.walletClient = params.walletClient;
13
+ }
14
+ }
15
+ async initialize(walletClient) {
16
+ if (walletClient) {
17
+ this.walletClient = walletClient;
18
+ }
19
+ this.service = new EvmAirdropService({
20
+ contractAddress: this.contractAddress,
21
+ chainId: this.chainId,
22
+ walletClient: this.walletClient
23
+ });
24
+ }
25
+ isInitialized() {
26
+ return !!this.service;
27
+ }
28
+ async getVersion() {
29
+ if (this.cachedVersion) {
30
+ return this.cachedVersion;
31
+ }
32
+ if (!this.service)
33
+ throw new Error('Strategy not initialized');
34
+ this.cachedVersion = await this.service.getVersion();
35
+ return this.cachedVersion;
36
+ }
37
+ async claim(claimData) {
38
+ if (!this.service)
39
+ throw new Error('Strategy not initialized');
40
+ const { proof, group, data, value, extraData } = claimData;
41
+ return this.service.claim({
42
+ proof,
43
+ group,
44
+ data,
45
+ value,
46
+ extraData
47
+ });
48
+ }
49
+ async checkClaimed(claimData) {
50
+ if (!this.service)
51
+ throw new Error('Strategy not initialized');
52
+ return this.service.isLeafUsed(claimData.leaf);
53
+ }
54
+ async batchCheckClaimed(leafs) {
55
+ if (!this.service)
56
+ throw new Error('Strategy not initialized');
57
+ return this.service.batchFetchClaimed(leafs);
58
+ }
59
+ async getNFT() {
60
+ if (!this.service)
61
+ throw new Error('Strategy not initialized');
62
+ return this.service.getNFT();
63
+ }
64
+ async getKycThreshold() {
65
+ if (!this.service)
66
+ throw new Error('Strategy not initialized');
67
+ return this.service.getKycThreshold();
68
+ }
69
+ async getClaimFee(contractAddress, amount) {
70
+ if (!this.service)
71
+ throw new Error('Strategy not initialized');
72
+ return this.service.getClaimFee(contractAddress, amount);
73
+ }
74
+ }
75
+ //# sourceMappingURL=EvmAirdropStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvmAirdropStrategy.js","sourceRoot":"","sources":["../../../../src/airdrop/strategies/EvmAirdropStrategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { IWalletClient } from '../types';
2
+ import { TonClient } from '@ton/ton';
3
+ export interface IAirdropStrategy {
4
+ getVersion(): Promise<string>;
5
+ claim(claimData: any, options?: {
6
+ onLoading?: () => void;
7
+ }): Promise<any>;
8
+ checkClaimed(claimData: any): Promise<boolean>;
9
+ isInitialized(): boolean;
10
+ initialize(walletClient?: IWalletClient): Promise<void>;
11
+ getPaused?(): Promise<boolean>;
12
+ batchCheckClaimed?(leafs: string[]): Promise<Array<{
13
+ result: boolean;
14
+ status: string;
15
+ }>>;
16
+ getNFT?(): Promise<string>;
17
+ getKycThreshold?(): Promise<bigint>;
18
+ getClaimFee?(contractAddress: string, amount: bigint): Promise<string | bigint>;
19
+ }
20
+ export interface IAirdropStrategyConstructor {
21
+ new (params: {
22
+ contractAddress: string;
23
+ chainId: string | number;
24
+ walletClient?: IWalletClient;
25
+ tonClient?: TonClient;
26
+ }): IAirdropStrategy;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IAirdropStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IAirdropStrategy.js","sourceRoot":"","sources":["../../../../src/airdrop/strategies/IAirdropStrategy.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { IAirdropStrategy } from './IAirdropStrategy';
2
+ export declare class StrategyCache {
3
+ private readOnlyStrategies;
4
+ private walletStrategies;
5
+ private getCacheKey;
6
+ getStrategy(contractAddress: string, chainId: string | number, chainType: string, hasWallet?: boolean): IAirdropStrategy | undefined;
7
+ setStrategy(contractAddress: string, chainId: string | number, chainType: string, strategy: IAirdropStrategy, hasWallet?: boolean): void;
8
+ clearStrategy(contractAddress: string, chainId: string | number, chainType: string, hasWallet?: boolean): void;
9
+ }
10
+ export declare const strategyCache: StrategyCache;
@@ -0,0 +1,28 @@
1
+ export class StrategyCache {
2
+ readOnlyStrategies = new Map();
3
+ walletStrategies = new Map();
4
+ getCacheKey(contractAddress, chainId, chainType) {
5
+ return `${chainType}:${contractAddress}:${chainId}`;
6
+ }
7
+ getStrategy(contractAddress, chainId, chainType, hasWallet = false) {
8
+ const cache = hasWallet ? this.walletStrategies : this.readOnlyStrategies;
9
+ const cacheKey = this.getCacheKey(contractAddress, chainId, chainType);
10
+ return cache.get(cacheKey);
11
+ }
12
+ setStrategy(contractAddress, chainId, chainType, strategy, hasWallet = false) {
13
+ const cache = hasWallet ? this.walletStrategies : this.readOnlyStrategies;
14
+ const cacheKey = this.getCacheKey(contractAddress, chainId, chainType);
15
+ cache.set(cacheKey, strategy);
16
+ }
17
+ clearStrategy(contractAddress, chainId, chainType, hasWallet) {
18
+ const cacheKey = this.getCacheKey(contractAddress, chainId, chainType);
19
+ if (hasWallet === undefined || hasWallet) {
20
+ this.walletStrategies.delete(cacheKey);
21
+ }
22
+ if (hasWallet === undefined || !hasWallet) {
23
+ this.readOnlyStrategies.delete(cacheKey);
24
+ }
25
+ }
26
+ }
27
+ export const strategyCache = new StrategyCache();
28
+ //# sourceMappingURL=StrategyCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StrategyCache.js","sourceRoot":"","sources":["../../../../src/airdrop/strategies/StrategyCache.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAChB,kBAAkB,GAAkC,IAAI,GAAG,EAAE,CAAC;IAC9D,gBAAgB,GAAkC,IAAI,GAAG,EAAE,CAAC;IAE5D,WAAW,CAAC,eAAuB,EAAE,OAAwB,EAAE,SAAiB;QACtF,OAAO,GAAG,SAAS,IAAI,eAAe,IAAI,OAAO,EAAE,CAAC;IACtD,CAAC;IAED,WAAW,CAAC,eAAuB,EAAE,OAAwB,EAAE,SAAiB,EAAE,YAAqB,KAAK;QAC1G,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,WAAW,CAAC,eAAuB,EAAE,OAAwB,EAAE,SAAiB,EAAE,QAA0B,EAAE,YAAqB,KAAK;QACtI,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACvE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,aAAa,CAAC,eAAuB,EAAE,OAAwB,EAAE,SAAiB,EAAE,SAAmB;QACrG,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACvE,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,EAAE,CAAC;YACzC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { TonClient } from '@ton/ton';
2
+ import { IWalletClient } from '../types';
3
+ import { IAirdropStrategy } from './IAirdropStrategy';
4
+ export declare class TonAirdropStrategy implements IAirdropStrategy {
5
+ private service;
6
+ private readonly contractAddress;
7
+ private readonly chainId;
8
+ private readonly tonClient?;
9
+ private walletClient?;
10
+ private cachedVersion;
11
+ constructor(params: {
12
+ contractAddress: string;
13
+ chainId: string | number;
14
+ walletClient?: IWalletClient;
15
+ tonClient?: TonClient;
16
+ });
17
+ initialize(walletClient?: IWalletClient): Promise<void>;
18
+ isInitialized(): boolean;
19
+ getVersion(): Promise<string>;
20
+ claim(claimData: any, options?: {
21
+ onLoading?: () => void;
22
+ }): Promise<any>;
23
+ checkClaimed(claimData: any): Promise<boolean>;
24
+ getPaused(): Promise<boolean>;
25
+ getClaimFee(contractAddress: string, amount: bigint): Promise<string>;
26
+ }
@@ -0,0 +1,60 @@
1
+ import { AirdropService as TonAirdropService } from '../core/ton/AirdropService';
2
+ export class TonAirdropStrategy {
3
+ service;
4
+ contractAddress;
5
+ chainId;
6
+ tonClient;
7
+ walletClient;
8
+ cachedVersion = null;
9
+ constructor(params) {
10
+ this.contractAddress = params.contractAddress;
11
+ this.chainId = params.chainId.toString();
12
+ this.tonClient = params.tonClient;
13
+ if (params.walletClient) {
14
+ this.walletClient = params.walletClient;
15
+ }
16
+ }
17
+ async initialize(walletClient) {
18
+ if (walletClient) {
19
+ this.walletClient = walletClient;
20
+ }
21
+ this.service = new TonAirdropService({
22
+ address: this.contractAddress,
23
+ chainId: this.chainId,
24
+ walletClient: this.walletClient,
25
+ tonClient: this.tonClient
26
+ });
27
+ }
28
+ isInitialized() {
29
+ return !!this.service;
30
+ }
31
+ async getVersion() {
32
+ if (!this.service)
33
+ throw new Error('Strategy not initialized');
34
+ if (!this.cachedVersion) {
35
+ this.cachedVersion = await this.service.getVersion();
36
+ }
37
+ return this.cachedVersion;
38
+ }
39
+ async claim(claimData, options) {
40
+ if (!this.service)
41
+ throw new Error('Strategy not initialized');
42
+ return this.service.claim(claimData, options);
43
+ }
44
+ async checkClaimed(claimData) {
45
+ if (!this.service)
46
+ throw new Error('Strategy not initialized');
47
+ return this.service.checkClaimed(claimData);
48
+ }
49
+ async getPaused() {
50
+ if (!this.service)
51
+ throw new Error('Strategy not initialized');
52
+ return this.service.getPaused();
53
+ }
54
+ async getClaimFee(contractAddress, amount) {
55
+ if (!this.service)
56
+ throw new Error('Strategy not initialized');
57
+ return this.service.getClaimFee(contractAddress, amount);
58
+ }
59
+ }
60
+ //# sourceMappingURL=TonAirdropStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TonAirdropStrategy.js","sourceRoot":"","sources":["../../../../src/airdrop/strategies/TonAirdropStrategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIjF,MAAM,OAAO,kBAAkB;IACrB,OAAO,CAAgC;IAC9B,eAAe,CAAS;IACxB,OAAO,CAAS;IAChB,SAAS,CAAa;IAC/B,YAAY,CAAgB;IAC5B,aAAa,GAAkB,IAAI,CAAC;IAE5C,YAAY,MAKX;QACC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAA4B,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,YAA4B;QAC3C,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,YAAY,GAAG,YAA4B,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACnC,OAAO,EAAE,IAAI,CAAC,eAAe;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,aAAa;QACX,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAc,EAAE,OAAoC;QAC9D,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAc;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,eAAuB,EAAE,MAAc;QACvD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;CACF"}
@@ -114,4 +114,9 @@ type SlugOptions = BaseAirdropOptions & {
114
114
  projectId?: never;
115
115
  };
116
116
  export type IAirdropOptions = ProjectIdOptions | SlugOptions;
117
+ export interface IContractConfig {
118
+ version?: string | null;
119
+ paused: boolean | null;
120
+ claimFee?: string | null;
121
+ }
117
122
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sign-global/tokentable",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,20 +1,17 @@
1
1
  import { TonClient } from '@ton/ton';
2
- import { TonConnectUI } from '@tonconnect/ui-react';
3
- import { AirdropService as TonAirdropService } from './core/ton/AirdropService';
4
- import { AirdropService as EvmAirdropService } from './core/evm/AirdropService';
5
- import { getAirdropPro, getAirdropProject, getAirdropQuery } from './services';
2
+ import { getAirdropPro, getAirdropProject, getAirdropQuery, getAirdropContractConfig } from './services';
6
3
  import {
7
- ChainId,
8
4
  ChainType,
9
- ETokenType,
10
- EvmAirdropVersionEnum,
11
5
  IAirdropClaim,
12
6
  IAirdropOptions,
7
+ IContractConfig,
13
8
  IProject,
14
9
  IWalletClient
15
10
  } from './types';
16
11
  import { getTonProjectIdByAddress } from './common';
17
- import { WalletClient as ViemWalletClient } from 'viem';
12
+ import { AirdropStrategyFactory } from './strategies/AirdropStrategyFactory';
13
+ import { IAirdropStrategy } from './strategies/IAirdropStrategy';
14
+ import { strategyCache } from './strategies/StrategyCache';
18
15
 
19
16
  export class AirdropClient {
20
17
  private tonClient?: TonClient;
@@ -23,11 +20,9 @@ export class AirdropClient {
23
20
  private endpoint?: string;
24
21
  private project: IProject | undefined;
25
22
  protected claims?: IAirdropClaim[];
26
- private contractInstanceWithWallet: TonAirdropService | EvmAirdropService | undefined;
27
- private contractInstanceWithoutWallet: TonAirdropService | EvmAirdropService | undefined;
28
23
  private projectPromise: Promise<void> | undefined;
29
24
  private claimHook: ((v: any) => any) | undefined;
30
- private cachedVersion: string | null = null;
25
+ private contractConfig: IContractConfig | null = null;
31
26
 
32
27
  constructor(params: IAirdropOptions) {
33
28
  if ('slug' in params) {
@@ -39,21 +34,41 @@ export class AirdropClient {
39
34
  this.projectPromise = this.initializeProjects();
40
35
  }
41
36
 
42
- protected async initializeProjects(address?: string) {
43
- let projectId: string | undefined = this.projectId;
44
- if (this.slug) {
45
- const res = await getAirdropPro(this.slug, this.endpoint);
46
- const projectMap = res?.childProjectMapping || {};
37
+ private async fetchProjectFromSlug(address?: string): Promise<string | undefined> {
38
+ if (!this.slug) return undefined;
39
+
40
+ const res = await getAirdropPro(this.slug, this.endpoint);
41
+ const projectMap = res?.childProjectMapping || {};
42
+
43
+ return getTonProjectIdByAddress({
44
+ address,
45
+ slug: this.slug,
46
+ data: projectMap
47
+ });
48
+ }
47
49
 
48
- let legacyProjectId: string | undefined;
49
- legacyProjectId = getTonProjectIdByAddress({ address, slug: this.slug, data: projectMap });
50
+ private async fetchProjectDetails(projectId: string): Promise<void> {
51
+ this.project = await getAirdropProject(projectId, this.endpoint);
52
+ }
50
53
 
51
- if (legacyProjectId) {
52
- projectId = legacyProjectId;
54
+ protected async initializeProjects(address?: string) {
55
+ try {
56
+ let projectId = this.projectId;
57
+
58
+ // If slug is provided, try to fetch project ID from slug
59
+ if (!projectId) {
60
+ projectId = await this.fetchProjectFromSlug(address);
53
61
  }
62
+
63
+ if (!projectId) {
64
+ throw new Error('Project ID is required and could not be determined');
65
+ }
66
+
67
+ // Fetch project details
68
+ await this.fetchProjectDetails(projectId);
69
+ } catch (error: any) {
70
+ throw new Error(`Failed to initialize project: ${error.message}`);
54
71
  }
55
- if (!projectId) throw new Error('Project ID is required');
56
- this.project = await getAirdropProject(projectId, this.endpoint);
57
72
  }
58
73
 
59
74
  async getProjectInfo() {
@@ -82,46 +97,45 @@ export class AirdropClient {
82
97
  return this.claims;
83
98
  }
84
99
 
85
- async getAirdropContractWrapper(options?: {
86
- walletClient?: IWalletClient;
87
- }): Promise<TonAirdropService | EvmAirdropService> {
100
+ public async getStrategy(walletClient?: IWalletClient): Promise<IAirdropStrategy> {
88
101
  const project = await this.getProjectInfo();
102
+ const hasWallet = !!walletClient;
103
+
104
+ // Try to get cached strategy
105
+ let strategy = strategyCache.getStrategy(
106
+ project.contractAddress,
107
+ project.chainId,
108
+ project.chainType,
109
+ hasWallet
110
+ );
89
111
 
90
- if (options?.walletClient) {
91
- if (!this.contractInstanceWithWallet) {
92
- const instance =
93
- project.chainType === ChainType.Evm
94
- ? new EvmAirdropService({
95
- contractAddress: project.contractAddress,
96
- chainId: Number(project.chainId) as ChainId,
97
- walletClient: options.walletClient as ViemWalletClient
98
- })
99
- : new TonAirdropService({
100
- chainId: project.chainId.toString(),
101
- address: project.contractAddress,
102
- walletClient: options.walletClient as TonConnectUI,
103
- tonClient: this.tonClient
104
- });
105
- this.contractInstanceWithWallet = instance;
106
- }
107
- return this.contractInstanceWithWallet;
108
- } else {
109
- if (!this.contractInstanceWithoutWallet) {
110
- const instance =
111
- project.chainType === ChainType.Evm
112
- ? new EvmAirdropService({
113
- contractAddress: project.contractAddress,
114
- chainId: Number(project.chainId) as ChainId
115
- })
116
- : new TonAirdropService({
117
- chainId: project.chainId.toString(),
118
- address: project.contractAddress,
119
- tonClient: this.tonClient
120
- });
121
- this.contractInstanceWithoutWallet = instance;
122
- }
123
- return this.contractInstanceWithoutWallet;
112
+ if (!strategy) {
113
+ // Create new strategy if not cached
114
+ strategy = AirdropStrategyFactory.createStrategy({
115
+ chainType: project.chainType,
116
+ contractAddress: project.contractAddress,
117
+ chainId: project.chainId,
118
+ walletClient,
119
+ tonClient: this.tonClient
120
+ });
121
+
122
+ // Initialize the strategy
123
+ await strategy.initialize(walletClient);
124
+
125
+ // Cache the initialized strategy
126
+ strategyCache.setStrategy(
127
+ project.contractAddress,
128
+ project.chainId,
129
+ project.chainType,
130
+ strategy,
131
+ hasWallet
132
+ );
133
+ } else if (hasWallet) {
134
+ // If we have a wallet and the strategy exists, just initialize with the new wallet
135
+ await strategy.initialize(walletClient);
124
136
  }
137
+
138
+ return strategy;
125
139
  }
126
140
 
127
141
  private getClaimDataById(claimId: string) {
@@ -139,115 +153,102 @@ export class AirdropClient {
139
153
  options?: { onLoading?: () => void }
140
154
  ) {
141
155
  const claimData = this.getClaimDataById(claimId);
142
- const project = await this.getProjectInfo();
143
-
144
- const contractWrapper = await this.getAirdropContractWrapper({
145
- walletClient
146
- });
147
-
148
- if (project.chainType === ChainType.Evm) {
149
- const version = await contractWrapper.getVersion();
150
- const needsFeeData = !(
151
- project.tokenType === ETokenType.Native &&
152
- [EvmAirdropVersionEnum.V3, EvmAirdropVersionEnum.V4].includes(version as EvmAirdropVersionEnum)
153
- );
154
-
155
- const value = needsFeeData ? await this.getClaimFee(BigInt(claimData.amount)) : undefined;
156
-
157
- let extraData = {
158
- isLegacy: true,
159
- attestationId: BigInt(1)
160
- };
161
- if (this.claimHook) {
162
- extraData = this.claimHook(claimData);
163
- }
156
+ const strategy = await this.getStrategy(walletClient);
164
157
 
165
- return (contractWrapper as EvmAirdropService).claim({
166
- proof: claimData.proof,
167
- group: claimData.group,
168
- data: claimData.data,
169
- value: value as bigint | undefined,
170
- extraData: extraData
171
- });
158
+ let extraData = {
159
+ isLegacy: true,
160
+ attestationId: BigInt(0)
161
+ }
162
+ if (this.claimHook) {
163
+ extraData = this.claimHook(claimData);
172
164
  }
173
165
 
174
- return (contractWrapper as TonAirdropService).claim(claimData, options);
166
+ return strategy.claim(claimData, options);
175
167
  }
176
168
 
177
169
  async checkClaimed(claimId: string): Promise<boolean> {
178
170
  const claimData = this.getClaimDataById(claimId);
179
- const project = await this.getProjectInfo();
171
+ const strategy = await this.getStrategy();
172
+ return strategy.checkClaimed(claimData);
173
+ }
180
174
 
181
- const contractWrapper = await this.getAirdropContractWrapper();
175
+ private async getContractConfig(): Promise<IContractConfig | null> {
176
+ try {
177
+ const project = await this.getProjectInfo();
182
178
 
183
- if (project.chainType === ChainType.Evm) {
184
- return (contractWrapper as EvmAirdropService).isLeafUsed(claimData.leaf);
179
+ if (!this.contractConfig) {
180
+ this.contractConfig = await getAirdropContractConfig({
181
+ chainId: project.chainId,
182
+ chainType: project.chainType,
183
+ contractAddress: project.contractAddress
184
+ }, this.endpoint);
185
+ }
186
+ return this.contractConfig;
187
+ } catch (error) {
188
+ console.error('Error fetching contract config:', error);
189
+ return null;
185
190
  }
186
-
187
- return (contractWrapper as TonAirdropService).checkClaimed(claimData);
188
191
  }
189
192
 
190
- async getPaused() {
191
- const project = await this.getProjectInfo();
192
- const contractWrapper = await this.getAirdropContractWrapper();
193
- if (project.chainType === ChainType.Evm) {
194
- throw new Error('EVM chain is not supported');
193
+ async getVersion(): Promise<string> {
194
+ const config = await this.getContractConfig();
195
+ if (config?.version) {
196
+ return config.version;
195
197
  }
196
- return (contractWrapper as TonAirdropService).getPaused();
198
+
199
+ const strategy = await this.getStrategy();
200
+ return strategy.getVersion();
197
201
  }
198
202
 
199
- async getVersion() {
200
- if (this.cachedVersion) {
201
- return this.cachedVersion;
203
+ async getPaused(): Promise<boolean> {
204
+ const config = await this.getContractConfig();
205
+ if (config && config?.paused !== null) {
206
+ return config.paused;
202
207
  }
203
- const contractWrapper = await this.getAirdropContractWrapper();
204
208
 
205
- this.cachedVersion = await contractWrapper?.getVersion();
206
- return this.cachedVersion;
209
+ const strategy = await this.getStrategy();
210
+ if (!strategy.getPaused) {
211
+ throw new Error('getPaused is not supported for this chain');
212
+ }
213
+ return strategy.getPaused();
207
214
  }
208
215
 
209
- async batchCheckClaimed() {
210
- const project = await this.getProjectInfo();
216
+ async getClaimFee(amount?: bigint): Promise<string | bigint> {
217
+ const config = await this.getContractConfig();
218
+ if (config?.claimFee) {
219
+ return config.claimFee;
220
+ }
211
221
 
212
- if (project.chainType === ChainType.Ton) {
213
- throw new Error('TON chain is not supported');
222
+ const strategy = await this.getStrategy();
223
+ if (!strategy.getClaimFee) {
224
+ throw new Error('getClaimFee is not supported for this chain');
214
225
  }
226
+ return strategy.getClaimFee(this.project?.contractAddress || '', amount || BigInt(0));
227
+ }
215
228
 
216
- const contractWrapper = await this.getAirdropContractWrapper();
229
+ async batchCheckClaimed(): Promise<{ result: boolean; status: string }[]> {
230
+ const strategy = await this.getStrategy();
231
+ if (!strategy.batchCheckClaimed) {
232
+ throw new Error('batchCheckClaimed is not supported for this chain');
233
+ }
217
234
  const leafs = this.claims?.map((it) => it.leaf);
218
-
219
235
  if (!leafs) return [];
220
-
221
- return (contractWrapper as EvmAirdropService).batchFetchClaimed(leafs);
236
+ return strategy.batchCheckClaimed(leafs);
222
237
  }
223
238
 
224
- async getNFT() {
225
- const project = await this.getProjectInfo();
226
-
227
- if (project.chainType === ChainType.Ton) {
228
- throw new Error('TON chain is not supported');
239
+ async getNFT(): Promise<string> {
240
+ const strategy = await this.getStrategy();
241
+ if (!strategy.getNFT) {
242
+ throw new Error('getNFT is not supported for this chain');
229
243
  }
230
-
231
- const contractWrapper = await this.getAirdropContractWrapper();
232
-
233
- return (contractWrapper as EvmAirdropService).getNFT();
244
+ return strategy.getNFT();
234
245
  }
235
246
 
236
- async getKycThreshold() {
237
- const project = await this.getProjectInfo();
238
-
239
- if (project.chainType === ChainType.Ton) {
240
- throw new Error('TON chain is not supported');
247
+ async getKycThreshold(): Promise<bigint> {
248
+ const strategy = await this.getStrategy();
249
+ if (!strategy.getKycThreshold) {
250
+ throw new Error('getKycThreshold is not supported for this chain');
241
251
  }
242
- const contractWrapper = await this.getAirdropContractWrapper();
243
- return (contractWrapper as EvmAirdropService).getKycThreshold();
244
- }
245
-
246
- async getClaimFee(amount?: bigint) {
247
- const project = await this.getProjectInfo();
248
-
249
- const contractWrapper = await this.getAirdropContractWrapper({});
250
-
251
- return contractWrapper.getClaimFee(project.contractAddress, amount || BigInt(1));
252
+ return strategy.getKycThreshold();
252
253
  }
253
254
  }