@triadxyz/triad-protocol 3.1.4-beta → 3.1.6-beta
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/dist/claim.d.ts +6 -3
- package/dist/claim.js +22 -8
- package/dist/index.d.ts +12 -0
- package/dist/index.js +21 -1
- package/dist/types/idl_triad_protocol.json +57 -0
- package/dist/types/index.d.ts +14 -3
- package/dist/types/triad_protocol.d.ts +57 -0
- package/dist/utils/helpers.js +4 -4
- package/dist/utils/merkle.d.ts +22 -0
- package/dist/utils/merkle.js +112 -0
- package/package.json +1 -1
package/dist/claim.d.ts
CHANGED
|
@@ -23,15 +23,18 @@ export default class Claim {
|
|
|
23
23
|
getClaimedUser(claimVault: PublicKey, user: PublicKey): Promise<import("./types").ClaimedUser>;
|
|
24
24
|
/**
|
|
25
25
|
* Claim Token
|
|
26
|
+
* @param claimData - Claim data
|
|
27
|
+
* @param vaultName - Vault name
|
|
28
|
+
* @param payer - Payer
|
|
29
|
+
* @param mint - Mint
|
|
26
30
|
* @param amount - Amount to claim
|
|
27
|
-
* @param merkleProof - Merkle proof
|
|
28
31
|
*/
|
|
29
|
-
claimToken({
|
|
32
|
+
claimToken({ mint, vaultName, payer, claimData, amount, isFirstComeFirstServed }: ClaimTokenArgs): Promise<string>;
|
|
30
33
|
/**
|
|
31
34
|
* Create Claim Vault
|
|
32
35
|
* @param args - Create Claim Vault Args
|
|
33
36
|
*/
|
|
34
|
-
createClaimVault({ totalAmount, totalUsers, name, isFirstComeFirstServed, endTs,
|
|
37
|
+
createClaimVault({ totalAmount, totalUsers, name, isFirstComeFirstServed, endTs, claimData, mint }: CreateClaimVaultArgs): Promise<string>;
|
|
35
38
|
/**
|
|
36
39
|
* Update Claim Vault Is Active
|
|
37
40
|
* @param isActive - Is active
|
package/dist/claim.js
CHANGED
|
@@ -16,6 +16,7 @@ const anchor_1 = require("@coral-xyz/anchor");
|
|
|
16
16
|
const helpers_1 = require("./utils/helpers");
|
|
17
17
|
const sendVersionedTransaction_1 = __importDefault(require("./utils/sendVersionedTransaction"));
|
|
18
18
|
const pda_1 = require("./utils/pda");
|
|
19
|
+
const merkle_1 = require("./utils/merkle");
|
|
19
20
|
class Claim {
|
|
20
21
|
constructor(program, rpcOptions) {
|
|
21
22
|
this.program = program;
|
|
@@ -55,21 +56,32 @@ class Claim {
|
|
|
55
56
|
}
|
|
56
57
|
/**
|
|
57
58
|
* Claim Token
|
|
59
|
+
* @param claimData - Claim data
|
|
60
|
+
* @param vaultName - Vault name
|
|
61
|
+
* @param payer - Payer
|
|
62
|
+
* @param mint - Mint
|
|
58
63
|
* @param amount - Amount to claim
|
|
59
|
-
* @param merkleProof - Merkle proof
|
|
60
64
|
*/
|
|
61
|
-
claimToken({
|
|
65
|
+
claimToken({ mint, vaultName, payer, claimData, amount, isFirstComeFirstServed }) {
|
|
66
|
+
var _a;
|
|
62
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
let proof = [];
|
|
69
|
+
if (!isFirstComeFirstServed) {
|
|
70
|
+
const { proofs } = (0, merkle_1.generateMerkleTree)(claimData);
|
|
71
|
+
proof = (_a = proofs.find((p) => p.user.toBase58() === this.program.provider.publicKey.toBase58())) === null || _a === void 0 ? void 0 : _a.proof;
|
|
72
|
+
}
|
|
63
73
|
const ixs = [
|
|
64
74
|
yield this.program.methods
|
|
65
75
|
.claimToken({
|
|
66
|
-
amount: new anchor_1.BN(amount),
|
|
67
|
-
merkleProof
|
|
76
|
+
amount: new anchor_1.BN(amount * Math.pow(10, 6)),
|
|
77
|
+
merkleProof: proof
|
|
68
78
|
})
|
|
69
79
|
.accounts({
|
|
70
80
|
signer: this.program.provider.publicKey,
|
|
81
|
+
payer,
|
|
71
82
|
mint,
|
|
72
|
-
claimVault
|
|
83
|
+
claimVault: (0, pda_1.getClaimVaultPDA)(this.program.programId, vaultName),
|
|
84
|
+
tokenProgram: (0, helpers_1.getTokenProgram)(mint)
|
|
73
85
|
})
|
|
74
86
|
.instruction()
|
|
75
87
|
];
|
|
@@ -80,12 +92,13 @@ class Claim {
|
|
|
80
92
|
* Create Claim Vault
|
|
81
93
|
* @param args - Create Claim Vault Args
|
|
82
94
|
*/
|
|
83
|
-
createClaimVault({ totalAmount, totalUsers, name, isFirstComeFirstServed, endTs,
|
|
95
|
+
createClaimVault({ totalAmount, totalUsers, name, isFirstComeFirstServed, endTs, claimData, mint }) {
|
|
84
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
const { merkleRoot } = (0, merkle_1.generateMerkleTree)(claimData);
|
|
85
98
|
const ixs = [
|
|
86
99
|
yield this.program.methods
|
|
87
100
|
.createClaimVault({
|
|
88
|
-
totalAmount: new anchor_1.BN(totalAmount),
|
|
101
|
+
totalAmount: new anchor_1.BN(totalAmount * Math.pow(10, 6)),
|
|
89
102
|
totalUsers: new anchor_1.BN(totalUsers),
|
|
90
103
|
name,
|
|
91
104
|
isFirstComeFirstServed,
|
|
@@ -94,7 +107,8 @@ class Claim {
|
|
|
94
107
|
})
|
|
95
108
|
.accounts({
|
|
96
109
|
signer: this.program.provider.publicKey,
|
|
97
|
-
mint
|
|
110
|
+
mint,
|
|
111
|
+
tokenProgram: (0, helpers_1.getTokenProgram)(mint)
|
|
98
112
|
})
|
|
99
113
|
.instruction()
|
|
100
114
|
];
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ import { TriadProtocol } from './types/triad_protocol';
|
|
|
5
5
|
import { CreateMarketArgs, OpenOrderArgs, UserTrade, CreateCustomerArgs, MarketBidOrderArgs, CancelBidOrderArgs, CancelAskOrderArgs, PlaceBidOrderArgs, PlaceAskOrderArgs, CollectMarketFeeArgs, CreatePoolArgs, BookOrder, MarketAskOrderArgs, RpcOptions, OrderDirection } from './types';
|
|
6
6
|
import Stake from './stake';
|
|
7
7
|
import Poseidon from './poseidon';
|
|
8
|
+
import Claim from './claim';
|
|
8
9
|
export * from './types';
|
|
9
10
|
export * from './utils/helpers';
|
|
11
|
+
export * from './utils/merkle';
|
|
10
12
|
export default class TriadProtocolClient {
|
|
11
13
|
private connection;
|
|
12
14
|
private wallet;
|
|
@@ -15,6 +17,7 @@ export default class TriadProtocolClient {
|
|
|
15
17
|
provider: AnchorProvider;
|
|
16
18
|
stake: Stake;
|
|
17
19
|
poseidon: Poseidon;
|
|
20
|
+
claim: Claim;
|
|
18
21
|
constructor(connection: Connection, wallet: Wallet, rpcOptions: RpcOptions);
|
|
19
22
|
/**
|
|
20
23
|
* Get All Pools
|
|
@@ -434,4 +437,13 @@ export default class TriadProtocolClient {
|
|
|
434
437
|
* @param question - Question
|
|
435
438
|
*/
|
|
436
439
|
updatePoolQuestion(poolId: number, question: string): Promise<string>;
|
|
440
|
+
/**
|
|
441
|
+
* Update Customer Fee
|
|
442
|
+
* @param customerId - Customer ID
|
|
443
|
+
* @param feeBps - Fee in basis points
|
|
444
|
+
*/
|
|
445
|
+
updateCustomerFee({ customerId, feeBps }: {
|
|
446
|
+
customerId: number;
|
|
447
|
+
feeBps: number;
|
|
448
|
+
}): Promise<string>;
|
|
437
449
|
}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const web3_js_1 = require("@solana/web3.js");
|
|
30
30
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
31
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
31
32
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
32
33
|
const idl_triad_protocol_json_1 = __importDefault(require("./types/idl_triad_protocol.json"));
|
|
33
34
|
const types_1 = require("./types");
|
|
@@ -38,9 +39,10 @@ const sendVersionedTransaction_1 = __importDefault(require("./utils/sendVersione
|
|
|
38
39
|
const swap_1 = require("./utils/swap");
|
|
39
40
|
const stake_1 = __importDefault(require("./stake"));
|
|
40
41
|
const poseidon_1 = __importDefault(require("./poseidon"));
|
|
41
|
-
const
|
|
42
|
+
const claim_1 = __importDefault(require("./claim"));
|
|
42
43
|
__exportStar(require("./types"), exports);
|
|
43
44
|
__exportStar(require("./utils/helpers"), exports);
|
|
45
|
+
__exportStar(require("./utils/merkle"), exports);
|
|
44
46
|
class TriadProtocolClient {
|
|
45
47
|
constructor(connection, wallet, rpcOptions) {
|
|
46
48
|
this.connection = connection;
|
|
@@ -52,6 +54,7 @@ class TriadProtocolClient {
|
|
|
52
54
|
this.program = new anchor_1.Program(idl_triad_protocol_json_1.default, this.provider);
|
|
53
55
|
this.stake = new stake_1.default(this.program, this.rpcOptions);
|
|
54
56
|
this.poseidon = new poseidon_1.default(this.program, this.rpcOptions);
|
|
57
|
+
this.claim = new claim_1.default(this.program, this.rpcOptions);
|
|
55
58
|
}
|
|
56
59
|
/**
|
|
57
60
|
* Get All Pools
|
|
@@ -1145,5 +1148,22 @@ class TriadProtocolClient {
|
|
|
1145
1148
|
return (0, sendVersionedTransaction_1.default)(this.program, ixs, this.rpcOptions);
|
|
1146
1149
|
});
|
|
1147
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Update Customer Fee
|
|
1153
|
+
* @param customerId - Customer ID
|
|
1154
|
+
* @param feeBps - Fee in basis points
|
|
1155
|
+
*/
|
|
1156
|
+
updateCustomerFee({ customerId, feeBps }) {
|
|
1157
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1158
|
+
const ixs = [];
|
|
1159
|
+
ixs.push(yield this.program.methods
|
|
1160
|
+
.updateCustomerFee({ id: customerId, feeBps })
|
|
1161
|
+
.accounts({
|
|
1162
|
+
signer: this.program.provider.publicKey
|
|
1163
|
+
})
|
|
1164
|
+
.instruction());
|
|
1165
|
+
return (0, sendVersionedTransaction_1.default)(this.program, ixs, this.rpcOptions);
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1148
1168
|
}
|
|
1149
1169
|
exports.default = TriadProtocolClient;
|
|
@@ -2566,6 +2566,47 @@
|
|
|
2566
2566
|
}
|
|
2567
2567
|
]
|
|
2568
2568
|
},
|
|
2569
|
+
{
|
|
2570
|
+
"name": "update_customer_fee",
|
|
2571
|
+
"discriminator": [218, 240, 1, 38, 34, 166, 40, 25],
|
|
2572
|
+
"accounts": [
|
|
2573
|
+
{
|
|
2574
|
+
"name": "signer",
|
|
2575
|
+
"writable": true,
|
|
2576
|
+
"signer": true
|
|
2577
|
+
},
|
|
2578
|
+
{
|
|
2579
|
+
"name": "customer",
|
|
2580
|
+
"writable": true,
|
|
2581
|
+
"pda": {
|
|
2582
|
+
"seeds": [
|
|
2583
|
+
{
|
|
2584
|
+
"kind": "const",
|
|
2585
|
+
"value": [99, 117, 115, 116, 111, 109, 101, 114]
|
|
2586
|
+
},
|
|
2587
|
+
{
|
|
2588
|
+
"kind": "arg",
|
|
2589
|
+
"path": "args.id"
|
|
2590
|
+
}
|
|
2591
|
+
]
|
|
2592
|
+
}
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
"name": "system_program",
|
|
2596
|
+
"address": "11111111111111111111111111111111"
|
|
2597
|
+
}
|
|
2598
|
+
],
|
|
2599
|
+
"args": [
|
|
2600
|
+
{
|
|
2601
|
+
"name": "args",
|
|
2602
|
+
"type": {
|
|
2603
|
+
"defined": {
|
|
2604
|
+
"name": "UpdateCustomerFeeArgs"
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
]
|
|
2609
|
+
},
|
|
2569
2610
|
{
|
|
2570
2611
|
"name": "update_market_end",
|
|
2571
2612
|
"discriminator": [10, 188, 22, 219, 206, 83, 67, 31],
|
|
@@ -4713,6 +4754,22 @@
|
|
|
4713
4754
|
]
|
|
4714
4755
|
}
|
|
4715
4756
|
},
|
|
4757
|
+
{
|
|
4758
|
+
"name": "UpdateCustomerFeeArgs",
|
|
4759
|
+
"type": {
|
|
4760
|
+
"kind": "struct",
|
|
4761
|
+
"fields": [
|
|
4762
|
+
{
|
|
4763
|
+
"name": "id",
|
|
4764
|
+
"type": "u16"
|
|
4765
|
+
},
|
|
4766
|
+
{
|
|
4767
|
+
"name": "fee_bps",
|
|
4768
|
+
"type": "u16"
|
|
4769
|
+
}
|
|
4770
|
+
]
|
|
4771
|
+
}
|
|
4772
|
+
},
|
|
4716
4773
|
{
|
|
4717
4774
|
"name": "UserTrade",
|
|
4718
4775
|
"type": {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -207,6 +207,15 @@ export type ClaimedUser = {
|
|
|
207
207
|
amount: number;
|
|
208
208
|
ts: number;
|
|
209
209
|
};
|
|
210
|
+
export interface ClaimData {
|
|
211
|
+
user: PublicKey;
|
|
212
|
+
amount: number;
|
|
213
|
+
}
|
|
214
|
+
export interface MerkleProof {
|
|
215
|
+
user: PublicKey;
|
|
216
|
+
amount: number;
|
|
217
|
+
proof: number[][];
|
|
218
|
+
}
|
|
210
219
|
export type PlaceBidOrderArgs = {
|
|
211
220
|
marketId: number;
|
|
212
221
|
orders: {
|
|
@@ -320,13 +329,15 @@ export type CreateClaimVaultArgs = {
|
|
|
320
329
|
name: string;
|
|
321
330
|
isFirstComeFirstServed: boolean;
|
|
322
331
|
endTs: number;
|
|
323
|
-
|
|
332
|
+
claimData: ClaimData[];
|
|
324
333
|
};
|
|
325
334
|
export type ClaimTokenArgs = {
|
|
326
335
|
amount: number;
|
|
327
|
-
|
|
336
|
+
vaultName: string;
|
|
328
337
|
mint: PublicKey;
|
|
329
|
-
|
|
338
|
+
payer: PublicKey;
|
|
339
|
+
claimData: ClaimData[];
|
|
340
|
+
isFirstComeFirstServed: boolean;
|
|
330
341
|
};
|
|
331
342
|
export type UpdateClaimVaultIsActiveArgs = {
|
|
332
343
|
isActive: boolean;
|
|
@@ -3599,6 +3599,47 @@ export type TriadProtocol = {
|
|
|
3599
3599
|
}
|
|
3600
3600
|
];
|
|
3601
3601
|
},
|
|
3602
|
+
{
|
|
3603
|
+
name: 'updateCustomerFee';
|
|
3604
|
+
discriminator: [218, 240, 1, 38, 34, 166, 40, 25];
|
|
3605
|
+
accounts: [
|
|
3606
|
+
{
|
|
3607
|
+
name: 'signer';
|
|
3608
|
+
writable: true;
|
|
3609
|
+
signer: true;
|
|
3610
|
+
},
|
|
3611
|
+
{
|
|
3612
|
+
name: 'customer';
|
|
3613
|
+
writable: true;
|
|
3614
|
+
pda: {
|
|
3615
|
+
seeds: [
|
|
3616
|
+
{
|
|
3617
|
+
kind: 'const';
|
|
3618
|
+
value: [99, 117, 115, 116, 111, 109, 101, 114];
|
|
3619
|
+
},
|
|
3620
|
+
{
|
|
3621
|
+
kind: 'arg';
|
|
3622
|
+
path: 'args.id';
|
|
3623
|
+
}
|
|
3624
|
+
];
|
|
3625
|
+
};
|
|
3626
|
+
},
|
|
3627
|
+
{
|
|
3628
|
+
name: 'systemProgram';
|
|
3629
|
+
address: '11111111111111111111111111111111';
|
|
3630
|
+
}
|
|
3631
|
+
];
|
|
3632
|
+
args: [
|
|
3633
|
+
{
|
|
3634
|
+
name: 'args';
|
|
3635
|
+
type: {
|
|
3636
|
+
defined: {
|
|
3637
|
+
name: 'updateCustomerFeeArgs';
|
|
3638
|
+
};
|
|
3639
|
+
};
|
|
3640
|
+
}
|
|
3641
|
+
];
|
|
3642
|
+
},
|
|
3602
3643
|
{
|
|
3603
3644
|
name: 'updateMarketEnd';
|
|
3604
3645
|
discriminator: [10, 188, 22, 219, 206, 83, 67, 31];
|
|
@@ -5758,6 +5799,22 @@ export type TriadProtocol = {
|
|
|
5758
5799
|
];
|
|
5759
5800
|
};
|
|
5760
5801
|
},
|
|
5802
|
+
{
|
|
5803
|
+
name: 'updateCustomerFeeArgs';
|
|
5804
|
+
type: {
|
|
5805
|
+
kind: 'struct';
|
|
5806
|
+
fields: [
|
|
5807
|
+
{
|
|
5808
|
+
name: 'id';
|
|
5809
|
+
type: 'u16';
|
|
5810
|
+
},
|
|
5811
|
+
{
|
|
5812
|
+
name: 'feeBps';
|
|
5813
|
+
type: 'u16';
|
|
5814
|
+
}
|
|
5815
|
+
];
|
|
5816
|
+
};
|
|
5817
|
+
},
|
|
5761
5818
|
{
|
|
5762
5819
|
name: 'userTrade';
|
|
5763
5820
|
type: {
|
package/dist/utils/helpers.js
CHANGED
|
@@ -166,11 +166,11 @@ const formatClaimVault = (account, address) => {
|
|
|
166
166
|
authority: account.authority.toString(),
|
|
167
167
|
initTs: account.initTs.toNumber(),
|
|
168
168
|
endTs: account.endTs.toNumber(),
|
|
169
|
-
totalAmount: account.totalAmount.toNumber(),
|
|
170
|
-
totalClaimed: account.totalClaimed.toNumber(),
|
|
169
|
+
totalAmount: account.totalAmount.toNumber() / Math.pow(10, 6),
|
|
170
|
+
totalClaimed: account.totalClaimed.toNumber() / Math.pow(10, 6),
|
|
171
171
|
totalUsers: account.totalUsers.toNumber(),
|
|
172
172
|
claimedUsers: account.claimedUsers.toNumber(),
|
|
173
|
-
tokenPerUser: account.tokenPerUser.toNumber(),
|
|
173
|
+
tokenPerUser: account.tokenPerUser.toNumber() / Math.pow(10, 6),
|
|
174
174
|
mint: account.mint.toBase58(),
|
|
175
175
|
isActive: account.isActive,
|
|
176
176
|
name: account.name,
|
|
@@ -184,7 +184,7 @@ const formatClaimedUser = (account, address) => {
|
|
|
184
184
|
user: address.toString(),
|
|
185
185
|
address: account.user.toString(),
|
|
186
186
|
claimVault: account.claimVault.toString(),
|
|
187
|
-
amount: account.amount.toNumber(),
|
|
187
|
+
amount: account.amount.toNumber() / Math.pow(10, 6),
|
|
188
188
|
ts: account.ts.toNumber()
|
|
189
189
|
};
|
|
190
190
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { ClaimData, MerkleProof } from '../types';
|
|
3
|
+
export declare class MerkleTree {
|
|
4
|
+
private leaves;
|
|
5
|
+
private tree;
|
|
6
|
+
private claimData;
|
|
7
|
+
constructor(claimData: ClaimData[]);
|
|
8
|
+
private generateLeaves;
|
|
9
|
+
private buildTree;
|
|
10
|
+
getRoot(): number[];
|
|
11
|
+
getProof(userPubkey: PublicKey, amount: number): number[][];
|
|
12
|
+
getAllProofs(): MerkleProof[];
|
|
13
|
+
verifyProof(userPubkey: PublicKey, amount: number, proof: number[][]): boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateMerkleTree(claimData: ClaimData[]): {
|
|
16
|
+
merkleRoot: number[];
|
|
17
|
+
proofs: MerkleProof[];
|
|
18
|
+
};
|
|
19
|
+
export declare function createClaimData(data: {
|
|
20
|
+
user: string;
|
|
21
|
+
amount: number;
|
|
22
|
+
}[]): ClaimData[];
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createClaimData = exports.generateMerkleTree = exports.MerkleTree = void 0;
|
|
4
|
+
const sha3_1 = require("@noble/hashes/sha3");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
class MerkleTree {
|
|
7
|
+
constructor(claimData) {
|
|
8
|
+
this.claimData = claimData;
|
|
9
|
+
this.leaves = this.generateLeaves(claimData);
|
|
10
|
+
this.tree = this.buildTree(this.leaves);
|
|
11
|
+
}
|
|
12
|
+
generateLeaves(claimData) {
|
|
13
|
+
return claimData.map((data) => {
|
|
14
|
+
const userBytes = data.user.toBytes();
|
|
15
|
+
const amountBytes = Buffer.alloc(8);
|
|
16
|
+
const amountLamports = BigInt(Math.floor(data.amount * Math.pow(10, 6)));
|
|
17
|
+
amountBytes.writeBigUInt64LE(amountLamports, 0);
|
|
18
|
+
const leafData = Buffer.concat([userBytes, amountBytes]);
|
|
19
|
+
return Buffer.from((0, sha3_1.keccak_256)(leafData));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
buildTree(leaves) {
|
|
23
|
+
if (leaves.length === 0) {
|
|
24
|
+
throw new Error('Cannot build tree with no leaves');
|
|
25
|
+
}
|
|
26
|
+
let currentLevel = [...leaves];
|
|
27
|
+
const tree = [currentLevel];
|
|
28
|
+
while (currentLevel.length > 1) {
|
|
29
|
+
const nextLevel = [];
|
|
30
|
+
for (let i = 0; i < currentLevel.length; i += 2) {
|
|
31
|
+
const left = currentLevel[i];
|
|
32
|
+
const right = i + 1 < currentLevel.length ? currentLevel[i + 1] : left;
|
|
33
|
+
const combined = left.compare(right) <= 0
|
|
34
|
+
? Buffer.concat([left, right])
|
|
35
|
+
: Buffer.concat([right, left]);
|
|
36
|
+
nextLevel.push(Buffer.from((0, sha3_1.keccak_256)(combined)));
|
|
37
|
+
}
|
|
38
|
+
currentLevel = nextLevel;
|
|
39
|
+
tree.push(currentLevel);
|
|
40
|
+
}
|
|
41
|
+
return tree;
|
|
42
|
+
}
|
|
43
|
+
getRoot() {
|
|
44
|
+
if (this.tree.length === 0) {
|
|
45
|
+
throw new Error('Tree not built');
|
|
46
|
+
}
|
|
47
|
+
const root = this.tree[this.tree.length - 1][0];
|
|
48
|
+
return Array.from(root);
|
|
49
|
+
}
|
|
50
|
+
getProof(userPubkey, amount) {
|
|
51
|
+
const targetLeaf = this.generateLeaves([{ user: userPubkey, amount }])[0];
|
|
52
|
+
const leafIndex = this.leaves.findIndex((leaf) => leaf.equals(targetLeaf));
|
|
53
|
+
if (leafIndex === -1) {
|
|
54
|
+
throw new Error('User not found in merkle tree');
|
|
55
|
+
}
|
|
56
|
+
const proof = [];
|
|
57
|
+
let currentIndex = leafIndex;
|
|
58
|
+
for (let level = 0; level < this.tree.length - 1; level++) {
|
|
59
|
+
const isRightNode = currentIndex % 2 === 1;
|
|
60
|
+
const siblingIndex = isRightNode ? currentIndex - 1 : currentIndex + 1;
|
|
61
|
+
if (siblingIndex < this.tree[level].length) {
|
|
62
|
+
proof.push(this.tree[level][siblingIndex]);
|
|
63
|
+
}
|
|
64
|
+
currentIndex = Math.floor(currentIndex / 2);
|
|
65
|
+
}
|
|
66
|
+
return proof.map((hash) => Array.from(hash));
|
|
67
|
+
}
|
|
68
|
+
getAllProofs() {
|
|
69
|
+
return this.claimData.map((data) => ({
|
|
70
|
+
user: data.user,
|
|
71
|
+
amount: data.amount,
|
|
72
|
+
proof: this.getProof(data.user, data.amount)
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
verifyProof(userPubkey, amount, proof) {
|
|
76
|
+
const leafData = Buffer.concat([
|
|
77
|
+
userPubkey.toBytes(),
|
|
78
|
+
(() => {
|
|
79
|
+
const amountBytes = Buffer.alloc(8);
|
|
80
|
+
const amountLamports = BigInt(Math.floor(amount * Math.pow(10, 6)));
|
|
81
|
+
amountBytes.writeBigUInt64LE(amountLamports, 0);
|
|
82
|
+
return amountBytes;
|
|
83
|
+
})()
|
|
84
|
+
]);
|
|
85
|
+
let currentHash = Buffer.from((0, sha3_1.keccak_256)(leafData));
|
|
86
|
+
for (const proofElement of proof) {
|
|
87
|
+
const proofBuffer = Buffer.from(proofElement);
|
|
88
|
+
const combined = currentHash.compare(proofBuffer) <= 0
|
|
89
|
+
? Buffer.concat([currentHash, proofBuffer])
|
|
90
|
+
: Buffer.concat([proofBuffer, currentHash]);
|
|
91
|
+
currentHash = Buffer.from((0, sha3_1.keccak_256)(combined));
|
|
92
|
+
}
|
|
93
|
+
const root = Buffer.from(this.getRoot());
|
|
94
|
+
return currentHash.equals(root);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.MerkleTree = MerkleTree;
|
|
98
|
+
function generateMerkleTree(claimData) {
|
|
99
|
+
const tree = new MerkleTree(claimData);
|
|
100
|
+
return {
|
|
101
|
+
merkleRoot: tree.getRoot(),
|
|
102
|
+
proofs: tree.getAllProofs()
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
exports.generateMerkleTree = generateMerkleTree;
|
|
106
|
+
function createClaimData(data) {
|
|
107
|
+
return data.map((item) => ({
|
|
108
|
+
user: new web3_js_1.PublicKey(item.user),
|
|
109
|
+
amount: item.amount
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
exports.createClaimData = createClaimData;
|