@sign-global/tokentable-core 1.0.0 → 1.2.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 +24 -0
- package/README.md +72 -0
- package/dist/index.d.mts +314 -224
- package/dist/index.d.ts +314 -224
- package/dist/index.js +489 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +486 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -3
- package/src/constants/chain-config.ts +20 -3
- package/src/constants/network.ts +53 -0
- package/src/contracts/evm/AirdropService.ts +18 -13
- package/src/contracts/index.ts +3 -0
- package/src/contracts/solana/AirdropSignatureClient.ts +2 -13
- package/src/contracts/solana/SignatureAirdropService.ts +2 -14
- package/src/contracts/solana/SolanaContractClient.ts +2 -2
- package/src/contracts/sui/BaseDistributorClient.ts +162 -0
- package/src/contracts/sui/DistributorWithFeeClient.ts +102 -0
- package/src/contracts/sui/SignatureAirdropService.ts +59 -0
- package/src/contracts/sui/SuiContractClient.ts +181 -0
- package/src/contracts/sui/__tests__/SignatureAirdropService.test.ts +71 -0
- package/src/services/airdrop/index.ts +4 -1
- package/src/types/index.ts +34 -6
- package/src/utils/api-client.ts +2 -2
- package/src/utils/utils.ts +8 -3
- package/vitest.config.ts +14 -0
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
SolanaAirdropService: () => AirdropService2,
|
|
44
44
|
SolanaSignatureAirdropService: () => SignatureAirdropService2,
|
|
45
45
|
SplTokenVersion: () => SplTokenVersion,
|
|
46
|
+
SuiSignatureAirdropService: () => SignatureAirdropService3,
|
|
46
47
|
SupportedChains: () => SupportedChains,
|
|
47
48
|
TonAirdropService: () => AirdropService3,
|
|
48
49
|
TonAirdropVersionEnum: () => TonAirdropVersionEnum,
|
|
@@ -85,6 +86,8 @@ __export(index_exports, {
|
|
|
85
86
|
signBrBTestnet: () => signBrBTestnet,
|
|
86
87
|
solanaDevNet: () => solanaDevNet,
|
|
87
88
|
solanaMainNet: () => solanaMainNet,
|
|
89
|
+
suiMainNet: () => suiMainNet,
|
|
90
|
+
suiTestNet: () => suiTestNet,
|
|
88
91
|
tonMainNet: () => tonMainNet,
|
|
89
92
|
tonTestNet: () => tonTestNet
|
|
90
93
|
});
|
|
@@ -94,6 +97,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
94
97
|
var import_chains = require("viem/chains");
|
|
95
98
|
|
|
96
99
|
// src/constants/network.ts
|
|
100
|
+
var import_client = require("@mysten/sui/client");
|
|
97
101
|
var import_sdk = require("@tonconnect/sdk");
|
|
98
102
|
var import_viem = require("viem");
|
|
99
103
|
var mevmDevNet = (0, import_viem.defineChain)({
|
|
@@ -240,6 +244,56 @@ var signBrBTestnet = /* @__PURE__ */ (0, import_viem.defineChain)({
|
|
|
240
244
|
},
|
|
241
245
|
testnet: true
|
|
242
246
|
});
|
|
247
|
+
var suiTestNet = {
|
|
248
|
+
id: "testnet",
|
|
249
|
+
name: "Sui Testnet",
|
|
250
|
+
network: "Sui Testnet",
|
|
251
|
+
nativeCurrency: {
|
|
252
|
+
decimals: 9,
|
|
253
|
+
name: "Sui",
|
|
254
|
+
symbol: "SUI"
|
|
255
|
+
},
|
|
256
|
+
rpcUrls: {
|
|
257
|
+
public: {
|
|
258
|
+
http: [(0, import_client.getFullnodeUrl)("testnet")]
|
|
259
|
+
},
|
|
260
|
+
default: {
|
|
261
|
+
http: [(0, import_client.getFullnodeUrl)("testnet")]
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
blockExplorers: {
|
|
265
|
+
default: {
|
|
266
|
+
name: "sui scan",
|
|
267
|
+
url: "https://testnet.suivision.xyz/"
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
testnet: true
|
|
271
|
+
};
|
|
272
|
+
var suiMainNet = {
|
|
273
|
+
id: "mainnet",
|
|
274
|
+
name: "Sui Mainnet",
|
|
275
|
+
network: "Sui Mainnet",
|
|
276
|
+
nativeCurrency: {
|
|
277
|
+
decimals: 9,
|
|
278
|
+
name: "Sui",
|
|
279
|
+
symbol: "SUI"
|
|
280
|
+
},
|
|
281
|
+
rpcUrls: {
|
|
282
|
+
public: {
|
|
283
|
+
http: [(0, import_client.getFullnodeUrl)("mainnet")]
|
|
284
|
+
},
|
|
285
|
+
default: {
|
|
286
|
+
http: [(0, import_client.getFullnodeUrl)("mainnet")]
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
blockExplorers: {
|
|
290
|
+
default: {
|
|
291
|
+
name: "sui scan",
|
|
292
|
+
url: "https://suivision.xyz/"
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
testnet: false
|
|
296
|
+
};
|
|
243
297
|
|
|
244
298
|
// src/constants/chain-config.ts
|
|
245
299
|
var import_sdk2 = require("@tonconnect/sdk");
|
|
@@ -277,8 +331,8 @@ var ChainConfig = {
|
|
|
277
331
|
rpcUrl: "https://zetachain-mainnet.g.alchemy.com/v2/1tmk0FrhwTJHXh0XIyae7_SXw1lDCjgs"
|
|
278
332
|
},
|
|
279
333
|
[import_chains.arbitrum.id]: {
|
|
280
|
-
contractAddress: "
|
|
281
|
-
rpcUrl:
|
|
334
|
+
contractAddress: "0xeD09c23677D02f4f486E55f0f081cfc114EEa53b",
|
|
335
|
+
rpcUrl: "https://arb-mainnet.g.alchemy.com/v2/udrqNPSB6i5n5L6QSM31Ng72h_hFOrVT"
|
|
282
336
|
},
|
|
283
337
|
[import_chains.berachainTestnet.id]: {
|
|
284
338
|
contractAddress: "",
|
|
@@ -326,6 +380,14 @@ var ChainConfig = {
|
|
|
326
380
|
[solanaMainNet.id]: {
|
|
327
381
|
contractAddress: "",
|
|
328
382
|
rpcUrl: solanaMainNet.rpcUrls.default.http[0]
|
|
383
|
+
},
|
|
384
|
+
[suiTestNet.id]: {
|
|
385
|
+
contractAddress: "0xb99be918b901c472b9839871b0341bf53a4d94a19312008a2e6c98908c92b778",
|
|
386
|
+
rpcUrl: suiTestNet.rpcUrls.default.http[0]
|
|
387
|
+
},
|
|
388
|
+
[suiMainNet.id]: {
|
|
389
|
+
contractAddress: "",
|
|
390
|
+
rpcUrl: suiMainNet.rpcUrls.default.http[0]
|
|
329
391
|
}
|
|
330
392
|
};
|
|
331
393
|
var SupportedChains = [
|
|
@@ -3735,6 +3797,7 @@ var ChainType = /* @__PURE__ */ ((ChainType2) => {
|
|
|
3735
3797
|
ChainType2["Evm"] = "evm";
|
|
3736
3798
|
ChainType2["Ton"] = "ton";
|
|
3737
3799
|
ChainType2["Solana"] = "solana";
|
|
3800
|
+
ChainType2["Sui"] = "sui";
|
|
3738
3801
|
return ChainType2;
|
|
3739
3802
|
})(ChainType || {});
|
|
3740
3803
|
var AirdropSigIdentityTypeEnum = /* @__PURE__ */ ((AirdropSigIdentityTypeEnum2) => {
|
|
@@ -3790,7 +3853,7 @@ async function getOrCreateAssociatedTokenAccount({
|
|
|
3790
3853
|
payer,
|
|
3791
3854
|
mint,
|
|
3792
3855
|
owner,
|
|
3793
|
-
signTransaction,
|
|
3856
|
+
signTransaction: signTransaction2,
|
|
3794
3857
|
allowOwnerOffCurve = false,
|
|
3795
3858
|
commitment,
|
|
3796
3859
|
programId = import_spl_token.TOKEN_PROGRAM_ID,
|
|
@@ -3823,7 +3886,7 @@ async function getOrCreateAssociatedTokenAccount({
|
|
|
3823
3886
|
console.log(blockhash, "blockhash");
|
|
3824
3887
|
transaction.feePayer = await payer;
|
|
3825
3888
|
transaction.recentBlockhash = blockhash;
|
|
3826
|
-
const signed = await
|
|
3889
|
+
const signed = await signTransaction2(transaction);
|
|
3827
3890
|
const signature = await connection.sendRawTransaction(signed.serialize());
|
|
3828
3891
|
const latestBlockhash = await connection.getLatestBlockhash();
|
|
3829
3892
|
await connection.confirmTransaction(
|
|
@@ -3899,11 +3962,16 @@ var getCustomNaNoId = () => {
|
|
|
3899
3962
|
const nanoid = (0, import_nanoid.customAlphabet)("1234567890abcdefghijklmnopqrstuvwxyz", 10);
|
|
3900
3963
|
return nanoid();
|
|
3901
3964
|
};
|
|
3902
|
-
var safeParseJSON = (str) => {
|
|
3965
|
+
var safeParseJSON = (str, defaultValue = {}) => {
|
|
3966
|
+
if (!str || typeof str !== "string") {
|
|
3967
|
+
return defaultValue;
|
|
3968
|
+
}
|
|
3903
3969
|
try {
|
|
3904
|
-
|
|
3970
|
+
const parsed = JSON.parse(str);
|
|
3971
|
+
return parsed !== null && parsed !== void 0 ? parsed : defaultValue;
|
|
3905
3972
|
} catch (error) {
|
|
3906
|
-
|
|
3973
|
+
console.warn("Failed to parse JSON:", error);
|
|
3974
|
+
return defaultValue;
|
|
3907
3975
|
}
|
|
3908
3976
|
};
|
|
3909
3977
|
var isBeforeByUnix = (unix) => {
|
|
@@ -3971,7 +4039,7 @@ var ApiClient = class _ApiClient {
|
|
|
3971
4039
|
}
|
|
3972
4040
|
const res = await fetch(finalUrl, init);
|
|
3973
4041
|
const [status, resData] = await Promise.all([res.status, res.json()]);
|
|
3974
|
-
if (status < 200
|
|
4042
|
+
if (status < 200 || status >= 300 || resData?.success !== true) {
|
|
3975
4043
|
return Promise.reject(resData);
|
|
3976
4044
|
}
|
|
3977
4045
|
return resData.data;
|
|
@@ -4150,22 +4218,27 @@ var AirdropService = class {
|
|
|
4150
4218
|
return this.airdropV3FeeClient.getFeelessThreshold();
|
|
4151
4219
|
}
|
|
4152
4220
|
async getClaimFee(address, amount) {
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
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 {
|
|
4221
|
+
try {
|
|
4222
|
+
const feeCollector = await this.feeCollectors(this.options.contractAddress);
|
|
4223
|
+
if (!feeCollector || feeCollector === ZERO_ADDRESS) {
|
|
4165
4224
|
return void 0;
|
|
4166
4225
|
}
|
|
4226
|
+
const feeClient = this.getFeeClient(feeCollector);
|
|
4227
|
+
const fee = await feeClient.getFee(address, amount);
|
|
4228
|
+
const version = await this.getVersion();
|
|
4229
|
+
if (version === "0.3.0" /* V3 */) {
|
|
4230
|
+
const threshold = await this.getFeelessThreshold();
|
|
4231
|
+
if (isGreaterThan(Number(amount), Number(threshold))) {
|
|
4232
|
+
return fee;
|
|
4233
|
+
} else {
|
|
4234
|
+
return void 0;
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
return fee;
|
|
4238
|
+
} catch (error) {
|
|
4239
|
+
console.error("Failed to get claim fee:", error);
|
|
4240
|
+
throw new Error(`Failed to calculate claim fee: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
4167
4241
|
}
|
|
4168
|
-
return fee;
|
|
4169
4242
|
}
|
|
4170
4243
|
async getKycThreshold() {
|
|
4171
4244
|
const kycClient = await this.getKycClient();
|
|
@@ -10480,7 +10553,9 @@ var createApiClient = (baseURL) => {
|
|
|
10480
10553
|
var getAirdropProject = async (projectId, baseURL) => {
|
|
10481
10554
|
const client = createApiClient(baseURL);
|
|
10482
10555
|
const res = await client.get(`/airdrop-open/projects/${projectId}`);
|
|
10483
|
-
if (!res)
|
|
10556
|
+
if (!res) {
|
|
10557
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
10558
|
+
}
|
|
10484
10559
|
const projectConfig = res?.themeConf;
|
|
10485
10560
|
const blockCountries = safeParseJSON(projectConfig?.blockCountries);
|
|
10486
10561
|
return {
|
|
@@ -12246,6 +12321,395 @@ var AirdropService3 = class {
|
|
|
12246
12321
|
return (0, import_core19.fromNano)(feeInfo.claimFee);
|
|
12247
12322
|
}
|
|
12248
12323
|
};
|
|
12324
|
+
|
|
12325
|
+
// src/contracts/sui/SuiContractClient.ts
|
|
12326
|
+
var import_client2 = require("@mysten/sui/client");
|
|
12327
|
+
var import_bcs = require("@mysten/sui/bcs");
|
|
12328
|
+
var import_transactions = require("@mysten/sui/transactions");
|
|
12329
|
+
var import_wallet_standard = require("@mysten/wallet-standard");
|
|
12330
|
+
var SuiContractClientBase = class {
|
|
12331
|
+
packageId;
|
|
12332
|
+
chainId;
|
|
12333
|
+
moduleName;
|
|
12334
|
+
distributorId;
|
|
12335
|
+
wallet;
|
|
12336
|
+
client;
|
|
12337
|
+
constructor(contractInfo) {
|
|
12338
|
+
this.packageId = contractInfo.packageId;
|
|
12339
|
+
this.chainId = contractInfo.chainId ? contractInfo.chainId : "mainnet";
|
|
12340
|
+
this.moduleName = contractInfo.moduleName;
|
|
12341
|
+
this.distributorId = contractInfo.distributorId;
|
|
12342
|
+
this.wallet = contractInfo.walletClient;
|
|
12343
|
+
this.client = new import_client2.SuiClient({ network: this.chainId, url: (0, import_client2.getFullnodeUrl)(this.chainId) });
|
|
12344
|
+
}
|
|
12345
|
+
async signAndExecute(tx) {
|
|
12346
|
+
if (!this.wallet) {
|
|
12347
|
+
throw new Error("Wallet not connected");
|
|
12348
|
+
}
|
|
12349
|
+
if (!this.wallet.features?.["sui:signTransaction"] && !this.wallet.features?.["sui:signTransactionBlock"]) {
|
|
12350
|
+
throw new Error("Wallet doesn't support transaction signing");
|
|
12351
|
+
}
|
|
12352
|
+
const accounts = await this.wallet.accounts;
|
|
12353
|
+
const client = this.client;
|
|
12354
|
+
if (!accounts || accounts.length === 0) {
|
|
12355
|
+
throw new Error("No wallet account connected");
|
|
12356
|
+
}
|
|
12357
|
+
const signerAccount = accounts[0];
|
|
12358
|
+
if ("setSenderIfNotSet" in tx) {
|
|
12359
|
+
tx.setSenderIfNotSet(signerAccount.address);
|
|
12360
|
+
}
|
|
12361
|
+
console.log(
|
|
12362
|
+
tx,
|
|
12363
|
+
await tx.toJSON({
|
|
12364
|
+
supportedIntents: [],
|
|
12365
|
+
client
|
|
12366
|
+
})
|
|
12367
|
+
);
|
|
12368
|
+
const chain = `sui:${this.chainId}`;
|
|
12369
|
+
const { signature, bytes } = await (0, import_wallet_standard.signTransaction)(this.wallet, {
|
|
12370
|
+
transaction: {
|
|
12371
|
+
async toJSON() {
|
|
12372
|
+
return typeof tx === "string" ? tx : await tx.toJSON({
|
|
12373
|
+
supportedIntents: [],
|
|
12374
|
+
client
|
|
12375
|
+
});
|
|
12376
|
+
}
|
|
12377
|
+
},
|
|
12378
|
+
account: signerAccount,
|
|
12379
|
+
chain
|
|
12380
|
+
});
|
|
12381
|
+
const result = await this.client.executeTransactionBlock({
|
|
12382
|
+
transactionBlock: bytes,
|
|
12383
|
+
signature,
|
|
12384
|
+
options: {
|
|
12385
|
+
showEffects: true,
|
|
12386
|
+
showEvents: true
|
|
12387
|
+
}
|
|
12388
|
+
});
|
|
12389
|
+
await this.waitForTx(result.digest);
|
|
12390
|
+
return result;
|
|
12391
|
+
}
|
|
12392
|
+
async waitForTx(digest) {
|
|
12393
|
+
return this.client.waitForTransaction({
|
|
12394
|
+
digest,
|
|
12395
|
+
options: { showEffects: true, showEvents: true }
|
|
12396
|
+
});
|
|
12397
|
+
}
|
|
12398
|
+
/**
|
|
12399
|
+
* 读取合约返回值(只读调用)
|
|
12400
|
+
* @param func Move function 名
|
|
12401
|
+
* @param typeArgs 类型参数
|
|
12402
|
+
* @param args Move function 参数
|
|
12403
|
+
*/
|
|
12404
|
+
async readMoveFunction(func, typeArgs = [], args = []) {
|
|
12405
|
+
const DEFAULT_SENDER = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
12406
|
+
const sender = this.wallet?.accounts?.[0]?.address || DEFAULT_SENDER;
|
|
12407
|
+
if (!sender) throw new Error("No wallet account selected");
|
|
12408
|
+
const tx = new import_transactions.Transaction();
|
|
12409
|
+
tx.moveCall({
|
|
12410
|
+
target: `${this.packageId}::${this.moduleName}::${func}`,
|
|
12411
|
+
typeArguments: typeArgs,
|
|
12412
|
+
arguments: args.map((arg) => {
|
|
12413
|
+
if (Array.isArray(arg)) return tx.pure(import_bcs.bcs.vector(import_bcs.bcs.vector(import_bcs.bcs.u8())).serialize(arg));
|
|
12414
|
+
if (typeof arg === "string" && arg.startsWith("0x")) return tx.object(arg);
|
|
12415
|
+
return tx.pure(arg);
|
|
12416
|
+
})
|
|
12417
|
+
});
|
|
12418
|
+
const res = await this.client.devInspectTransactionBlock({
|
|
12419
|
+
sender,
|
|
12420
|
+
transactionBlock: tx
|
|
12421
|
+
// ✅ 这里传 Transaction,不再报 TS 类型错误
|
|
12422
|
+
});
|
|
12423
|
+
console.log(res, "res");
|
|
12424
|
+
if (!res || !res.results?.[0]?.returnValues) {
|
|
12425
|
+
throw new Error(`Failed to read ${func}`);
|
|
12426
|
+
}
|
|
12427
|
+
return res.results[0].returnValues[0];
|
|
12428
|
+
}
|
|
12429
|
+
/**
|
|
12430
|
+
* 查询 Distributor MoveObject 的 fields
|
|
12431
|
+
*/
|
|
12432
|
+
async getObjectFields(objectId) {
|
|
12433
|
+
const res = await this.client.getObject({
|
|
12434
|
+
id: objectId,
|
|
12435
|
+
options: { showContent: true }
|
|
12436
|
+
});
|
|
12437
|
+
if (res.data?.content?.dataType !== "moveObject") {
|
|
12438
|
+
throw new Error(`Object ${objectId} is not a moveObject`);
|
|
12439
|
+
}
|
|
12440
|
+
return res.data.content.fields;
|
|
12441
|
+
}
|
|
12442
|
+
async getSharedObjectRef(tx, objectId, mutable) {
|
|
12443
|
+
const obj = await this.client.getObject({
|
|
12444
|
+
id: objectId,
|
|
12445
|
+
options: { showOwner: true }
|
|
12446
|
+
});
|
|
12447
|
+
console.log(obj, "obj");
|
|
12448
|
+
if (!obj.data) {
|
|
12449
|
+
throw new Error(`Object ${objectId} not found`);
|
|
12450
|
+
}
|
|
12451
|
+
if (!obj.data.owner?.Shared) {
|
|
12452
|
+
throw new Error(`Object ${objectId} is not a shared object`);
|
|
12453
|
+
}
|
|
12454
|
+
const initialSharedVersion = obj.data.owner.Shared.initial_shared_version;
|
|
12455
|
+
return tx.sharedObjectRef({
|
|
12456
|
+
objectId,
|
|
12457
|
+
initialSharedVersion: Number(initialSharedVersion),
|
|
12458
|
+
mutable
|
|
12459
|
+
});
|
|
12460
|
+
}
|
|
12461
|
+
};
|
|
12462
|
+
|
|
12463
|
+
// src/contracts/sui/BaseDistributorClient.ts
|
|
12464
|
+
var import_transactions2 = require("@mysten/sui/transactions");
|
|
12465
|
+
var import_bcs2 = require("@mysten/sui/bcs");
|
|
12466
|
+
var SuiBaseDistributorClient = class extends SuiContractClientBase {
|
|
12467
|
+
constructor(info) {
|
|
12468
|
+
super({ ...info, moduleName: "base_distributor" });
|
|
12469
|
+
}
|
|
12470
|
+
async createDistributor(coinType, projectId, projectRegistryId) {
|
|
12471
|
+
const tx = new import_transactions2.Transaction();
|
|
12472
|
+
const projectIdBytes = import_bcs2.bcs.vector(import_bcs2.bcs.u8()).serialize(Array.from(Buffer.from(projectId, "utf8")));
|
|
12473
|
+
tx.moveCall({
|
|
12474
|
+
target: `${this.packageId}::${this.moduleName}::create_and_share_distributor`,
|
|
12475
|
+
typeArguments: [coinType],
|
|
12476
|
+
arguments: [tx.pure(projectIdBytes), tx.object(projectRegistryId)]
|
|
12477
|
+
});
|
|
12478
|
+
const result = await this.signAndExecute(tx);
|
|
12479
|
+
console.log(result, "res");
|
|
12480
|
+
let distributorId;
|
|
12481
|
+
if (result.effects?.created) {
|
|
12482
|
+
const createdObj = result.effects.created.find(
|
|
12483
|
+
(obj) => obj.owner === "Shared" || obj.owner?.Shared
|
|
12484
|
+
// 某些版本字段是对象
|
|
12485
|
+
);
|
|
12486
|
+
if (createdObj) {
|
|
12487
|
+
distributorId = createdObj.reference.objectId;
|
|
12488
|
+
}
|
|
12489
|
+
}
|
|
12490
|
+
return {
|
|
12491
|
+
txResult: result,
|
|
12492
|
+
distributorId
|
|
12493
|
+
};
|
|
12494
|
+
}
|
|
12495
|
+
async setBaseParams(coinType, startTime, endTime, authorizedSigner, ownerCapId) {
|
|
12496
|
+
const tx = new import_transactions2.Transaction();
|
|
12497
|
+
tx.moveCall({
|
|
12498
|
+
target: `${this.packageId}::${this.moduleName}::set_base_params`,
|
|
12499
|
+
typeArguments: [coinType],
|
|
12500
|
+
arguments: [
|
|
12501
|
+
tx.object(this.distributorId),
|
|
12502
|
+
tx.pure.u64(startTime),
|
|
12503
|
+
tx.pure.u64(endTime),
|
|
12504
|
+
tx.pure.address(authorizedSigner),
|
|
12505
|
+
tx.object(ownerCapId)
|
|
12506
|
+
]
|
|
12507
|
+
});
|
|
12508
|
+
return this.signAndExecute(tx);
|
|
12509
|
+
}
|
|
12510
|
+
async togglePause(coinType, ownerCapId) {
|
|
12511
|
+
const tx = new import_transactions2.Transaction();
|
|
12512
|
+
tx.moveCall({
|
|
12513
|
+
target: `${this.packageId}::${this.moduleName}::toggle_pause`,
|
|
12514
|
+
typeArguments: [coinType],
|
|
12515
|
+
arguments: [tx.object(this.distributorId), tx.object(ownerCapId)]
|
|
12516
|
+
});
|
|
12517
|
+
return this.signAndExecute(tx);
|
|
12518
|
+
}
|
|
12519
|
+
async getDistributorInfo() {
|
|
12520
|
+
console.log(this.client, this.distributorId, "distributorId");
|
|
12521
|
+
const res = await this.client.getObject({
|
|
12522
|
+
id: this.distributorId,
|
|
12523
|
+
options: { showContent: true }
|
|
12524
|
+
});
|
|
12525
|
+
const content = res.data?.content;
|
|
12526
|
+
const fields = content?.fields;
|
|
12527
|
+
const match = content?.type.match(/<(.+)>$/);
|
|
12528
|
+
const coinType = match ? match[1] : "";
|
|
12529
|
+
return {
|
|
12530
|
+
startTime: fields?.start_time,
|
|
12531
|
+
endTime: fields?.end_time,
|
|
12532
|
+
signer: fields?.authorized_signer,
|
|
12533
|
+
ownerCapId: fields?.owner_cap_id,
|
|
12534
|
+
version: fields?.version ? String.fromCharCode(...fields.version) : void 0,
|
|
12535
|
+
feeCollector: fields?.fee_collector,
|
|
12536
|
+
token: coinType,
|
|
12537
|
+
tokenBalance: fields?.token_balance,
|
|
12538
|
+
paused: fields?.paused
|
|
12539
|
+
};
|
|
12540
|
+
}
|
|
12541
|
+
async getVersion() {
|
|
12542
|
+
const { version } = await this.getDistributorInfo();
|
|
12543
|
+
return version;
|
|
12544
|
+
}
|
|
12545
|
+
async getPaused() {
|
|
12546
|
+
const { paused } = await this.getDistributorInfo();
|
|
12547
|
+
return paused;
|
|
12548
|
+
}
|
|
12549
|
+
async getClaimFee(amount) {
|
|
12550
|
+
return 0n;
|
|
12551
|
+
}
|
|
12552
|
+
async batchFetchClaimed(coinType, claimIds) {
|
|
12553
|
+
const claimIdsBytes = claimIds.map((id) => Array.from(new TextEncoder().encode(id)));
|
|
12554
|
+
const res = await this.readMoveFunction(
|
|
12555
|
+
"get_claim_status",
|
|
12556
|
+
[coinType],
|
|
12557
|
+
[this.distributorId, claimIdsBytes]
|
|
12558
|
+
);
|
|
12559
|
+
console.log(res, "claims");
|
|
12560
|
+
const [data, type] = res;
|
|
12561
|
+
if (type === "vector<bool>" && data) {
|
|
12562
|
+
const uint8Array = new Uint8Array(data);
|
|
12563
|
+
return Array.from(import_bcs2.bcs.vector(import_bcs2.bcs.bool()).parse(uint8Array));
|
|
12564
|
+
}
|
|
12565
|
+
return [];
|
|
12566
|
+
}
|
|
12567
|
+
async getDistributorId(projectId, projectRegistryId) {
|
|
12568
|
+
const distributorId = await this.readMoveFunction(
|
|
12569
|
+
"get_distributor_by_project_id",
|
|
12570
|
+
[],
|
|
12571
|
+
[projectRegistryId, Array.from(Buffer.from(projectId, "utf8"))]
|
|
12572
|
+
);
|
|
12573
|
+
console.log(distributorId, "id");
|
|
12574
|
+
return distributorId.Some;
|
|
12575
|
+
}
|
|
12576
|
+
async getOwnerCapId() {
|
|
12577
|
+
const objects = await this.client.getOwnedObjects({
|
|
12578
|
+
owner: this.wallet.accounts[0].address,
|
|
12579
|
+
filter: {
|
|
12580
|
+
StructType: `${this.packageId}::ownable::OwnerCap`
|
|
12581
|
+
}
|
|
12582
|
+
});
|
|
12583
|
+
console.log(objects, "objects");
|
|
12584
|
+
const ownerCapId = objects.data[0]?.data?.objectId;
|
|
12585
|
+
return ownerCapId;
|
|
12586
|
+
}
|
|
12587
|
+
};
|
|
12588
|
+
|
|
12589
|
+
// src/contracts/sui/DistributorWithFeeClient.ts
|
|
12590
|
+
var import_transactions3 = require("@mysten/sui/transactions");
|
|
12591
|
+
var import_bcs3 = require("@mysten/sui/bcs");
|
|
12592
|
+
var SuiDistributorWithFeeClient = class extends SuiContractClientBase {
|
|
12593
|
+
constructor(info) {
|
|
12594
|
+
super({ ...info, moduleName: "fungible_token_with_fees_distributor" });
|
|
12595
|
+
}
|
|
12596
|
+
async prepareFeePayment(totalFeesStr, feeTokenType, tx) {
|
|
12597
|
+
const totalFees = BigInt(totalFeesStr);
|
|
12598
|
+
const coins = await this.client.getCoins({
|
|
12599
|
+
owner: this.wallet.accounts[0].address,
|
|
12600
|
+
coinType: feeTokenType
|
|
12601
|
+
});
|
|
12602
|
+
const suitableCoin = coins.data.find((coin) => BigInt(coin.balance) >= totalFees);
|
|
12603
|
+
if (suitableCoin) {
|
|
12604
|
+
if (BigInt(suitableCoin.balance) === totalFees) {
|
|
12605
|
+
return tx.object(suitableCoin.coinObjectId);
|
|
12606
|
+
}
|
|
12607
|
+
const [feeCoin] = tx.splitCoins(tx.object(suitableCoin.coinObjectId), [tx.pure(import_bcs3.bcs.u64().serialize(totalFees))]);
|
|
12608
|
+
return feeCoin;
|
|
12609
|
+
}
|
|
12610
|
+
throw new Error(`Insufficient balance. Required: ${totalFeesStr}, Available coins: ${coins.data.length}`);
|
|
12611
|
+
}
|
|
12612
|
+
async claimWithFee(coinType, feeCollector, data) {
|
|
12613
|
+
console.log(data, feeCollector, this.distributorId, "data");
|
|
12614
|
+
const recipients = data.map((item) => item.recipient);
|
|
12615
|
+
const claimIds = data.map((item) => item.claimId);
|
|
12616
|
+
const signatures = data.map((item) => item.signature);
|
|
12617
|
+
function encodeClaimDataWithFees(timestamp, amount, fees) {
|
|
12618
|
+
const tsBytes = import_bcs3.bcs.u64().serialize(timestamp).toBytes();
|
|
12619
|
+
const amtBytes = import_bcs3.bcs.u64().serialize(amount).toBytes();
|
|
12620
|
+
const feeBytes = import_bcs3.bcs.u64().serialize(fees).toBytes();
|
|
12621
|
+
return Array.from(new Uint8Array([...tsBytes, ...amtBytes, ...feeBytes]));
|
|
12622
|
+
}
|
|
12623
|
+
const datas = data.map((item) => {
|
|
12624
|
+
const claimData = item.data;
|
|
12625
|
+
return encodeClaimDataWithFees(
|
|
12626
|
+
BigInt(claimData.claimableTimestamp),
|
|
12627
|
+
BigInt(claimData.claimableAmount),
|
|
12628
|
+
BigInt(item.fees || "0")
|
|
12629
|
+
);
|
|
12630
|
+
});
|
|
12631
|
+
const totalFees = data.map((item) => BigInt(item.fees || "0")).reduce((sum, fee) => sum + fee, BigInt(0));
|
|
12632
|
+
const tx = new import_transactions3.Transaction();
|
|
12633
|
+
const distributor = await this.getSharedObjectRef(tx, this.distributorId, true);
|
|
12634
|
+
const feeConfig = await this.getSharedObjectRef(tx, feeCollector, true);
|
|
12635
|
+
const clock = await this.getSharedObjectRef(tx, "0x6", false);
|
|
12636
|
+
const hexToBytes = (hex) => Array.from(Buffer.from(hex.replace(/^0x/, ""), "hex"));
|
|
12637
|
+
const feeTokenType = "0x2::sui::SUI";
|
|
12638
|
+
const [feeCoin] = tx.splitCoins(
|
|
12639
|
+
tx.gas,
|
|
12640
|
+
// 用 gas 对象作为源
|
|
12641
|
+
[tx.pure(import_bcs3.bcs.u64().serialize(totalFees))]
|
|
12642
|
+
);
|
|
12643
|
+
tx.moveCall({
|
|
12644
|
+
target: `${this.packageId}::${this.moduleName}::claim_with_fees`,
|
|
12645
|
+
arguments: [
|
|
12646
|
+
distributor,
|
|
12647
|
+
feeConfig,
|
|
12648
|
+
tx.pure(import_bcs3.bcs.vector(import_bcs3.bcs.Address).serialize(recipients)),
|
|
12649
|
+
// recipients: vector<address>
|
|
12650
|
+
tx.pure(
|
|
12651
|
+
import_bcs3.bcs.vector(import_bcs3.bcs.vector(import_bcs3.bcs.u8())).serialize(claimIds.map((id) => Array.from(new TextEncoder().encode(id))))
|
|
12652
|
+
),
|
|
12653
|
+
// claim_ids: vector<vector<u8>>
|
|
12654
|
+
tx.pure(import_bcs3.bcs.vector(import_bcs3.bcs.vector(import_bcs3.bcs.u8())).serialize(datas)),
|
|
12655
|
+
// claim_datas: vector<vector<u8>>
|
|
12656
|
+
tx.pure(import_bcs3.bcs.vector(import_bcs3.bcs.vector(import_bcs3.bcs.u8())).serialize(signatures.map((sig) => hexToBytes(sig)))),
|
|
12657
|
+
// signatures: vector<vector<u8>>
|
|
12658
|
+
feeCoin,
|
|
12659
|
+
clock
|
|
12660
|
+
],
|
|
12661
|
+
typeArguments: [coinType, feeTokenType]
|
|
12662
|
+
// Token类型, Fee类型
|
|
12663
|
+
});
|
|
12664
|
+
const res = await this.signAndExecute(tx);
|
|
12665
|
+
return res.digest;
|
|
12666
|
+
}
|
|
12667
|
+
};
|
|
12668
|
+
|
|
12669
|
+
// src/contracts/sui/SignatureAirdropService.ts
|
|
12670
|
+
var SignatureAirdropService3 = class {
|
|
12671
|
+
options;
|
|
12672
|
+
constructor(options) {
|
|
12673
|
+
const chainConfig = getChainConfig(options.chainId);
|
|
12674
|
+
this.options = {
|
|
12675
|
+
...options,
|
|
12676
|
+
packageId: chainConfig.contractAddress
|
|
12677
|
+
};
|
|
12678
|
+
}
|
|
12679
|
+
get baseDistributorClient() {
|
|
12680
|
+
if (!this.options) {
|
|
12681
|
+
throw new Error("options is empty");
|
|
12682
|
+
}
|
|
12683
|
+
return new SuiBaseDistributorClient(this.options);
|
|
12684
|
+
}
|
|
12685
|
+
get feeDistributorClient() {
|
|
12686
|
+
if (!this.options) {
|
|
12687
|
+
throw new Error("options is empty");
|
|
12688
|
+
}
|
|
12689
|
+
return new SuiDistributorWithFeeClient(this.options);
|
|
12690
|
+
}
|
|
12691
|
+
async getVersion() {
|
|
12692
|
+
return this.baseDistributorClient.getVersion();
|
|
12693
|
+
}
|
|
12694
|
+
async getClaimFee(address, amount) {
|
|
12695
|
+
const fee = await this.baseDistributorClient.getClaimFee(amount);
|
|
12696
|
+
return fee;
|
|
12697
|
+
}
|
|
12698
|
+
async batchFetchClaimed(userClaimIds) {
|
|
12699
|
+
const res = await this.baseDistributorClient.batchFetchClaimed(this.options.coinType, userClaimIds);
|
|
12700
|
+
return res;
|
|
12701
|
+
}
|
|
12702
|
+
async getPaused() {
|
|
12703
|
+
return this.baseDistributorClient.getPaused();
|
|
12704
|
+
}
|
|
12705
|
+
async getContractInfo() {
|
|
12706
|
+
return this.baseDistributorClient.getDistributorInfo();
|
|
12707
|
+
}
|
|
12708
|
+
async claim(data, recipient) {
|
|
12709
|
+
const { feeCollector } = await this.getContractInfo();
|
|
12710
|
+
return this.feeDistributorClient.claimWithFee(this.options.coinType, feeCollector, data);
|
|
12711
|
+
}
|
|
12712
|
+
};
|
|
12249
12713
|
// Annotate the CommonJS export names for ESM import in node:
|
|
12250
12714
|
0 && (module.exports = {
|
|
12251
12715
|
AirdropSigIdentityTypeEnum,
|
|
@@ -12261,6 +12725,7 @@ var AirdropService3 = class {
|
|
|
12261
12725
|
SolanaAirdropService,
|
|
12262
12726
|
SolanaSignatureAirdropService,
|
|
12263
12727
|
SplTokenVersion,
|
|
12728
|
+
SuiSignatureAirdropService,
|
|
12264
12729
|
SupportedChains,
|
|
12265
12730
|
TonAirdropService,
|
|
12266
12731
|
TonAirdropVersionEnum,
|
|
@@ -12303,6 +12768,8 @@ var AirdropService3 = class {
|
|
|
12303
12768
|
signBrBTestnet,
|
|
12304
12769
|
solanaDevNet,
|
|
12305
12770
|
solanaMainNet,
|
|
12771
|
+
suiMainNet,
|
|
12772
|
+
suiTestNet,
|
|
12306
12773
|
tonMainNet,
|
|
12307
12774
|
tonTestNet
|
|
12308
12775
|
});
|