@ercworldio/blockchain-shared 1.0.5-dev.7-PROJ-1469.4 → 1.0.5-dev.7-PROJ-1469.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.
- package/build/chains/networks_dev.json +10 -0
- package/build/services/Redis.js +2 -2
- package/build/services/RedisPubSub.js +1 -1
- package/build/services/solana/escrow/services/EscrowAdminUtility.d.ts +9 -0
- package/build/services/solana/escrow/services/EscrowAdminUtility.d.ts.map +1 -1
- package/build/services/solana/escrow/services/EscrowAdminUtility.js +65 -27
- package/build/services/solana/escrow/services/TreasuryWithdrawalSignature.d.ts +53 -0
- package/build/services/solana/escrow/services/TreasuryWithdrawalSignature.d.ts.map +1 -0
- package/build/services/solana/escrow/services/TreasuryWithdrawalSignature.js +89 -0
- package/build/services/solana/escrow/types/types.d.ts +16 -0
- package/build/services/solana/escrow/types/types.d.ts.map +1 -1
- package/build/services/types/claim.d.ts +1 -0
- package/build/services/types/claim.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -135,6 +135,16 @@
|
|
|
135
135
|
"source": "wallet"
|
|
136
136
|
}
|
|
137
137
|
],
|
|
138
|
+
"quicknodeStreams": [
|
|
139
|
+
{
|
|
140
|
+
"network": "solana-devnet",
|
|
141
|
+
"dataset": "block",
|
|
142
|
+
"name": "solana-escrow-logs",
|
|
143
|
+
"listConfig": {
|
|
144
|
+
"key": "escrow-address"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
],
|
|
138
148
|
"quicknodeNotificationConfig": [
|
|
139
149
|
{
|
|
140
150
|
"name": "escrow-sol-dev",
|
package/build/services/Redis.js
CHANGED
|
@@ -277,7 +277,7 @@ class Redis {
|
|
|
277
277
|
try {
|
|
278
278
|
const pref = `${this.prefix}-`;
|
|
279
279
|
const normalizedKey = expiredKey.startsWith(pref) ? expiredKey.slice(pref.length) : expiredKey;
|
|
280
|
-
this.logger.info(`Redis: key expired: ${normalizedKey}`);
|
|
280
|
+
// this.logger.info(`Redis: key expired: ${normalizedKey}`);
|
|
281
281
|
let value = null;
|
|
282
282
|
try {
|
|
283
283
|
value = yield this.get_object(expiredKey);
|
|
@@ -381,7 +381,7 @@ class Redis {
|
|
|
381
381
|
get_object(_key_1) {
|
|
382
382
|
return __awaiter(this, arguments, void 0, function* (_key, use_prefix = true) {
|
|
383
383
|
const key = this.get_key(_key, use_prefix);
|
|
384
|
-
this.logger.info(`Redis: Getting object with key: ${key}`);
|
|
384
|
+
// this.logger.info(`Redis: Getting object with key: ${key}`);
|
|
385
385
|
const raw = yield this._get(key);
|
|
386
386
|
return raw ? JSON.parse(raw) : null;
|
|
387
387
|
});
|
|
@@ -110,7 +110,7 @@ class RedisPubSub {
|
|
|
110
110
|
this.logger.info(`RedisPubSub: pSubscribe: Subscribed to pattern: ${pattern}`);
|
|
111
111
|
yield this.subscriber.pSubscribe(pattern, (eventKey) => __awaiter(this, void 0, void 0, function* () {
|
|
112
112
|
try {
|
|
113
|
-
this.logger.info(`RedisPubSub: pSubscribe: Received subscriber event: ${event.eventName}. eventkey: ${eventKey}`)
|
|
113
|
+
// this.logger.info(`RedisPubSub: pSubscribe: Received subscriber event: ${event.eventName}. eventkey: ${eventKey}`)
|
|
114
114
|
// Get the value before it expires (if possible) or use the key
|
|
115
115
|
const pref = `${this.prefix}-`;
|
|
116
116
|
if (eventKey.startsWith(pref))
|
|
@@ -92,6 +92,15 @@ export declare class EscrowAdminUtility {
|
|
|
92
92
|
* @returns string - signature
|
|
93
93
|
*/
|
|
94
94
|
withdraw_batch(chain_id: ChainId, token_address: string, recipients: BatchReceiver[], signer?: Keypair): Promise<string>;
|
|
95
|
+
/** Per-request PDAs the folded batch path expects: receiver timelock override + commitment. */
|
|
96
|
+
private request_pdas;
|
|
97
|
+
/**
|
|
98
|
+
* Builds the Ed25519SigVerify instruction the program scans to enforce treasury multisig.
|
|
99
|
+
* Each request contributes its signers' approvals over that request's message (which binds
|
|
100
|
+
* the committed amount + token + chain + request id). Returns null when no request carries
|
|
101
|
+
* signatures, so plain batches send just the withdraw instruction.
|
|
102
|
+
*/
|
|
103
|
+
private buildBatchTreasuryEd25519;
|
|
95
104
|
/** @dev this might fail if the recipient does not have an ATA - take care of it in funding worker task */
|
|
96
105
|
private batch_withdraw_spl;
|
|
97
106
|
private batch_withdraw_sol;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EscrowAdminUtility.d.ts","sourceRoot":"","sources":["../../../../../src/services/solana/escrow/services/EscrowAdminUtility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAoB,SAAS,EAA0E,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGjL,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"EscrowAdminUtility.d.ts","sourceRoot":"","sources":["../../../../../src/services/solana/escrow/services/EscrowAdminUtility.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,7 @@ const TransactionsService_1 = require("./TransactionsService");
|
|
|
56
56
|
const Errors_1 = __importDefault(require("./Errors"));
|
|
57
57
|
const TokenAccountService_1 = require("./TokenAccountService");
|
|
58
58
|
const SolanaTokenProgramCache_1 = require("./SolanaTokenProgramCache");
|
|
59
|
+
const TreasuryWithdrawalSignature_1 = require("./TreasuryWithdrawalSignature");
|
|
59
60
|
class EscrowAdminUtility {
|
|
60
61
|
constructor(program, provider) {
|
|
61
62
|
this.program = program;
|
|
@@ -375,6 +376,43 @@ class EscrowAdminUtility {
|
|
|
375
376
|
}
|
|
376
377
|
});
|
|
377
378
|
}
|
|
379
|
+
/** Per-request PDAs the folded batch path expects: receiver timelock override + commitment. */
|
|
380
|
+
request_pdas(receiver, request_id) {
|
|
381
|
+
const ridBuf = Buffer.alloc(8);
|
|
382
|
+
ridBuf.writeBigUInt64LE(BigInt(request_id));
|
|
383
|
+
const [receiverTimelock] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('receiver-timelock'), receiver.toBytes()], this.program.programId);
|
|
384
|
+
const [commitment] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('withdrawal'), ridBuf], this.program.programId);
|
|
385
|
+
return { receiverTimelock, commitment };
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Builds the Ed25519SigVerify instruction the program scans to enforce treasury multisig.
|
|
389
|
+
* Each request contributes its signers' approvals over that request's message (which binds
|
|
390
|
+
* the committed amount + token + chain + request id). Returns null when no request carries
|
|
391
|
+
* signatures, so plain batches send just the withdraw instruction.
|
|
392
|
+
*/
|
|
393
|
+
buildBatchTreasuryEd25519(chainId, tokenMint, recipients) {
|
|
394
|
+
var _a;
|
|
395
|
+
const entries = [];
|
|
396
|
+
for (const r of recipients) {
|
|
397
|
+
if (!((_a = r.signatures) === null || _a === void 0 ? void 0 : _a.length))
|
|
398
|
+
continue;
|
|
399
|
+
const message = (0, TreasuryWithdrawalSignature_1.buildWithdrawalApprovalMessage)({
|
|
400
|
+
recipient: new web3_js_1.PublicKey(r.receiver_pubkey),
|
|
401
|
+
tokenMint,
|
|
402
|
+
committedAmount: BigInt(r.amount_in_lamports),
|
|
403
|
+
chainId: BigInt(chainId),
|
|
404
|
+
requestId: BigInt(r.request_id),
|
|
405
|
+
});
|
|
406
|
+
for (const s of r.signatures) {
|
|
407
|
+
entries.push({
|
|
408
|
+
publicKey: new web3_js_1.PublicKey(s.signer).toBytes(),
|
|
409
|
+
signature: (0, TreasuryWithdrawalSignature_1.decodeEd25519Signature)(s.signature),
|
|
410
|
+
message,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return entries.length ? (0, TreasuryWithdrawalSignature_1.buildTreasuryEd25519Instruction)(entries) : null;
|
|
415
|
+
}
|
|
378
416
|
/** @dev this might fail if the recipient does not have an ATA - take care of it in funding worker task */
|
|
379
417
|
batch_withdraw_spl(chainId, mint, recipients, signer) {
|
|
380
418
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -384,13 +422,17 @@ class EscrowAdminUtility {
|
|
|
384
422
|
const amounts = recipients.map(r => new anchor.BN(r.amount_in_lamports));
|
|
385
423
|
const net_amounts = recipients.map(r => new anchor.BN(r.net_amount_in_lamports));
|
|
386
424
|
const request_ids = recipients.map(r => new anchor.BN(r.request_id));
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
425
|
+
// Per request: [recipient, recipient_token_account, receiver_timelock, commitment]
|
|
426
|
+
const receivers = recipients.flatMap(r => {
|
|
427
|
+
const wallet = new web3_js_1.PublicKey(r.receiver_pubkey);
|
|
428
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, wallet);
|
|
429
|
+
const { receiverTimelock, commitment } = this.request_pdas(wallet, r.request_id);
|
|
430
|
+
return [
|
|
431
|
+
{ isSigner: false, pubkey: wallet, isWritable: true },
|
|
432
|
+
{ isSigner: false, pubkey: ata, isWritable: true },
|
|
433
|
+
{ isSigner: false, pubkey: receiverTimelock, isWritable: false },
|
|
434
|
+
{ isSigner: false, pubkey: commitment, isWritable: true },
|
|
435
|
+
];
|
|
394
436
|
});
|
|
395
437
|
const ix = yield this.program.methods
|
|
396
438
|
.batchWithdrawTokens(new anchor.BN(chainId), request_ids, amounts, net_amounts)
|
|
@@ -404,7 +446,9 @@ class EscrowAdminUtility {
|
|
|
404
446
|
})
|
|
405
447
|
.remainingAccounts(receivers)
|
|
406
448
|
.instruction();
|
|
407
|
-
|
|
449
|
+
// Prepend the treasury multisig proof when any request in the batch requires it.
|
|
450
|
+
const ed25519 = this.buildBatchTreasuryEd25519(chainId, mint, recipients);
|
|
451
|
+
const signature = yield this.sendTransaction(ed25519 ? [ed25519, ix] : [ix], signer);
|
|
408
452
|
yield this.waitForConfirmation(signature, "confirmed");
|
|
409
453
|
return signature;
|
|
410
454
|
});
|
|
@@ -415,14 +459,17 @@ class EscrowAdminUtility {
|
|
|
415
459
|
const vaultAuthority = EscrowService.findVaultAuthorityPda(this.program.programId);
|
|
416
460
|
const amounts = recipients.map(r => new anchor.BN(r.amount_in_lamports));
|
|
417
461
|
const net_amounts = recipients.map(r => new anchor.BN(r.net_amount_in_lamports));
|
|
418
|
-
const receivers = recipients.map(r => {
|
|
419
|
-
return {
|
|
420
|
-
isSigner: false,
|
|
421
|
-
pubkey: new web3_js_1.PublicKey(r.receiver_pubkey),
|
|
422
|
-
isWritable: true
|
|
423
|
-
};
|
|
424
|
-
});
|
|
425
462
|
const request_ids = recipients.map(r => new anchor.BN(r.request_id));
|
|
463
|
+
// Per request: [recipient, receiver_timelock, commitment]
|
|
464
|
+
const receivers = recipients.flatMap(r => {
|
|
465
|
+
const wallet = new web3_js_1.PublicKey(r.receiver_pubkey);
|
|
466
|
+
const { receiverTimelock, commitment } = this.request_pdas(wallet, r.request_id);
|
|
467
|
+
return [
|
|
468
|
+
{ isSigner: false, pubkey: wallet, isWritable: true },
|
|
469
|
+
{ isSigner: false, pubkey: receiverTimelock, isWritable: false },
|
|
470
|
+
{ isSigner: false, pubkey: commitment, isWritable: true },
|
|
471
|
+
];
|
|
472
|
+
});
|
|
426
473
|
const ix = yield this.program.methods
|
|
427
474
|
.batchWithdrawSol(new anchor.BN(chainId), request_ids, amounts, net_amounts)
|
|
428
475
|
.accountsPartial({
|
|
@@ -433,18 +480,9 @@ class EscrowAdminUtility {
|
|
|
433
480
|
})
|
|
434
481
|
.remainingAccounts(receivers)
|
|
435
482
|
.instruction();
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
// new Uint8Array(ixBuffer),
|
|
440
|
-
// new Uint8Array(ix.data)
|
|
441
|
-
// ])
|
|
442
|
-
// const transactionIx = new TransactionInstruction({
|
|
443
|
-
// programId: this.program.programId,
|
|
444
|
-
// data: ixData,
|
|
445
|
-
// keys: ix.keys
|
|
446
|
-
// })
|
|
447
|
-
const signature = yield this.sendTransaction([ix], signer);
|
|
483
|
+
// Prepend the treasury multisig proof when any request in the batch requires it.
|
|
484
|
+
const ed25519 = this.buildBatchTreasuryEd25519(chainId, web3_js_1.SystemProgram.programId, recipients);
|
|
485
|
+
const signature = yield this.sendTransaction(ed25519 ? [ed25519, ix] : [ix], signer);
|
|
448
486
|
return signature;
|
|
449
487
|
});
|
|
450
488
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
|
+
/**
|
|
3
|
+
* Treasury withdrawal approval message + Ed25519 assembly.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the escrow program's `build_withdrawal_message` and its Ed25519SigVerify layout so the
|
|
6
|
+
* batch-withdraw transaction the funding worker sends carries signatures the program accepts.
|
|
7
|
+
*/
|
|
8
|
+
/** One treasury manager/executive approval over a request's message. */
|
|
9
|
+
export interface TreasurySignatureInput {
|
|
10
|
+
/** Base58 signer pubkey — a current treasury manager/executive on-chain. */
|
|
11
|
+
signer: string;
|
|
12
|
+
/** 64-byte Ed25519 signature (base64/hex/base58). */
|
|
13
|
+
signature: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds the UTF-8 approval message a treasury signer approves. MUST match the program's
|
|
17
|
+
* `build_withdrawal_message` byte for byte, or verification fails.
|
|
18
|
+
*
|
|
19
|
+
* ERCWORLD Escrow Withdrawal Approval
|
|
20
|
+
* Version: 1
|
|
21
|
+
* Chain: <chainId>
|
|
22
|
+
* Request: <requestId>
|
|
23
|
+
* Recipient: <recipient base58>
|
|
24
|
+
* Token: <mint base58>
|
|
25
|
+
* Amount: <committed amount, raw base units>
|
|
26
|
+
*
|
|
27
|
+
* `Amount` is the committed (approved) amount — the net paid out is chosen later by the backend
|
|
28
|
+
* and bounded on-chain by TreasuryConfig.max_fee_delta. The title + Version line domain-separate
|
|
29
|
+
* the signature; bump Version in lockstep with the program on any format change.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildWithdrawalApprovalMessage(params: {
|
|
32
|
+
recipient: PublicKey;
|
|
33
|
+
tokenMint: PublicKey;
|
|
34
|
+
committedAmount: bigint;
|
|
35
|
+
chainId: bigint;
|
|
36
|
+
requestId: bigint;
|
|
37
|
+
}): Buffer;
|
|
38
|
+
/** Decode a 64-byte Ed25519 signature from base64, hex (0x-optional), or base58. */
|
|
39
|
+
export declare function decodeEd25519Signature(s: string): Uint8Array;
|
|
40
|
+
/** One fully-decoded signature entry: pubkey + signature over `message`. */
|
|
41
|
+
export interface Ed25519Entry {
|
|
42
|
+
publicKey: Uint8Array;
|
|
43
|
+
signature: Uint8Array;
|
|
44
|
+
message: Uint8Array;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Builds a single Ed25519SigVerify instruction carrying `entries` self-contained signatures
|
|
48
|
+
* (each entry's pubkey, signature and message live in this instruction's own data). This is the
|
|
49
|
+
* compact layout the program scans in `verify_treasury_threshold`; one instruction for the whole
|
|
50
|
+
* batch keeps the transaction far smaller than one instruction per signature.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildTreasuryEd25519Instruction(entries: Ed25519Entry[]): TransactionInstruction;
|
|
53
|
+
//# sourceMappingURL=TreasuryWithdrawalSignature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreasuryWithdrawalSignature.d.ts","sourceRoot":"","sources":["../../../../../src/services/solana/escrow/services/TreasuryWithdrawalSignature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGpF;;;;;GAKG;AAEH,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACnD,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAUT;AAED,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAU5D;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,sBAAsB,CAmC/F"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildWithdrawalApprovalMessage = buildWithdrawalApprovalMessage;
|
|
7
|
+
exports.decodeEd25519Signature = decodeEd25519Signature;
|
|
8
|
+
exports.buildTreasuryEd25519Instruction = buildTreasuryEd25519Instruction;
|
|
9
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
10
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
11
|
+
/**
|
|
12
|
+
* Builds the UTF-8 approval message a treasury signer approves. MUST match the program's
|
|
13
|
+
* `build_withdrawal_message` byte for byte, or verification fails.
|
|
14
|
+
*
|
|
15
|
+
* ERCWORLD Escrow Withdrawal Approval
|
|
16
|
+
* Version: 1
|
|
17
|
+
* Chain: <chainId>
|
|
18
|
+
* Request: <requestId>
|
|
19
|
+
* Recipient: <recipient base58>
|
|
20
|
+
* Token: <mint base58>
|
|
21
|
+
* Amount: <committed amount, raw base units>
|
|
22
|
+
*
|
|
23
|
+
* `Amount` is the committed (approved) amount — the net paid out is chosen later by the backend
|
|
24
|
+
* and bounded on-chain by TreasuryConfig.max_fee_delta. The title + Version line domain-separate
|
|
25
|
+
* the signature; bump Version in lockstep with the program on any format change.
|
|
26
|
+
*/
|
|
27
|
+
function buildWithdrawalApprovalMessage(params) {
|
|
28
|
+
const text = "ERCWORLD Escrow Withdrawal Approval\n" +
|
|
29
|
+
"Version: 1\n" +
|
|
30
|
+
`Chain: ${params.chainId}\n` +
|
|
31
|
+
`Request: ${params.requestId}\n` +
|
|
32
|
+
`Recipient: ${params.recipient.toBase58()}\n` +
|
|
33
|
+
`Token: ${params.tokenMint.toBase58()}\n` +
|
|
34
|
+
`Amount: ${params.committedAmount}`;
|
|
35
|
+
return Buffer.from(text, "utf8");
|
|
36
|
+
}
|
|
37
|
+
/** Decode a 64-byte Ed25519 signature from base64, hex (0x-optional), or base58. */
|
|
38
|
+
function decodeEd25519Signature(s) {
|
|
39
|
+
const b64 = Buffer.from(s, "base64");
|
|
40
|
+
if (b64.length === 64)
|
|
41
|
+
return b64;
|
|
42
|
+
const hex = s.startsWith("0x") ? s.slice(2) : s;
|
|
43
|
+
if (/^[0-9a-fA-F]{128}$/.test(hex))
|
|
44
|
+
return Buffer.from(hex, "hex");
|
|
45
|
+
try {
|
|
46
|
+
const b58 = bs58_1.default.decode(s);
|
|
47
|
+
if (b58.length === 64)
|
|
48
|
+
return b58;
|
|
49
|
+
}
|
|
50
|
+
catch ( /* fallthrough */_a) { /* fallthrough */ }
|
|
51
|
+
throw new Error("Invalid Ed25519 signature encoding (expected 64 bytes as base64/hex/base58)");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Builds a single Ed25519SigVerify instruction carrying `entries` self-contained signatures
|
|
55
|
+
* (each entry's pubkey, signature and message live in this instruction's own data). This is the
|
|
56
|
+
* compact layout the program scans in `verify_treasury_threshold`; one instruction for the whole
|
|
57
|
+
* batch keeps the transaction far smaller than one instruction per signature.
|
|
58
|
+
*/
|
|
59
|
+
function buildTreasuryEd25519Instruction(entries) {
|
|
60
|
+
const N = entries.length;
|
|
61
|
+
const OFFSETS_SIZE = 14;
|
|
62
|
+
const ENTRY_SIZE = 32 + 64; // pubkey + signature
|
|
63
|
+
const header = 2 + N * OFFSETS_SIZE;
|
|
64
|
+
const msgStart = header + N * ENTRY_SIZE;
|
|
65
|
+
const totalMsg = entries.reduce((s, e) => s + e.message.length, 0);
|
|
66
|
+
const data = Buffer.alloc(msgStart + totalMsg);
|
|
67
|
+
data[0] = N; // number of signatures
|
|
68
|
+
data[1] = 0; // padding
|
|
69
|
+
let msgCursor = msgStart;
|
|
70
|
+
for (let i = 0; i < N; i++) {
|
|
71
|
+
const base = 2 + i * OFFSETS_SIZE;
|
|
72
|
+
const pkOffset = header + i * ENTRY_SIZE;
|
|
73
|
+
const sigOffset = pkOffset + 32;
|
|
74
|
+
const msgOffset = msgCursor;
|
|
75
|
+
const msgLen = entries[i].message.length;
|
|
76
|
+
data.writeUInt16LE(sigOffset, base + 0); // signature_offset
|
|
77
|
+
data.writeUInt16LE(0xffff, base + 2); // signature_instruction_index (self)
|
|
78
|
+
data.writeUInt16LE(pkOffset, base + 4); // public_key_offset
|
|
79
|
+
data.writeUInt16LE(0xffff, base + 6); // public_key_instruction_index (self)
|
|
80
|
+
data.writeUInt16LE(msgOffset, base + 8); // message_data_offset
|
|
81
|
+
data.writeUInt16LE(msgLen, base + 10); // message_data_size
|
|
82
|
+
data.writeUInt16LE(0xffff, base + 12); // message_instruction_index (self)
|
|
83
|
+
data.set(entries[i].publicKey, pkOffset);
|
|
84
|
+
data.set(entries[i].signature, sigOffset);
|
|
85
|
+
data.set(entries[i].message, msgOffset);
|
|
86
|
+
msgCursor += msgLen;
|
|
87
|
+
}
|
|
88
|
+
return new web3_js_1.TransactionInstruction({ keys: [], programId: web3_js_1.Ed25519Program.programId, data });
|
|
89
|
+
}
|
|
@@ -11,10 +11,26 @@ export interface EncodedWithdrawSignature {
|
|
|
11
11
|
signer: string;
|
|
12
12
|
message: string;
|
|
13
13
|
}
|
|
14
|
+
/** A treasury manager/executive approval collected off-chain for one withdrawal request. */
|
|
15
|
+
export interface BatchTreasurySignature {
|
|
16
|
+
/** Base58 signer pubkey (must be a current treasury manager/executive on-chain). */
|
|
17
|
+
signer: string;
|
|
18
|
+
/** 64-byte Ed25519 signature, base64/hex/base58 — over the request's approval message. */
|
|
19
|
+
signature: string;
|
|
20
|
+
}
|
|
14
21
|
export interface BatchReceiver {
|
|
22
|
+
/** Approved (committed) amount — what the treasury signatures are bound to. */
|
|
15
23
|
amount_in_lamports: number;
|
|
24
|
+
/** Amount actually paid out after the backend's fee deduction. */
|
|
16
25
|
net_amount_in_lamports: number;
|
|
17
26
|
receiver_pubkey: PublicKey;
|
|
18
27
|
request_id: number;
|
|
28
|
+
/**
|
|
29
|
+
* Treasury approvals for this request. Required only when the token's amount band demands
|
|
30
|
+
* multisig (managers + executives > 0); leave empty/undefined otherwise. When present, the
|
|
31
|
+
* batch transaction prepends an Ed25519SigVerify instruction the program scans to enforce
|
|
32
|
+
* the threshold.
|
|
33
|
+
*/
|
|
34
|
+
signatures?: BatchTreasurySignature[];
|
|
19
35
|
}
|
|
20
36
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/services/solana/escrow/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3G,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;AACpH,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,eAAe,EAAE,SAAS,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/services/solana/escrow/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3G,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;AACpH,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,4FAA4F;AAC5F,MAAM,WAAW,sBAAsB;IACnC,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC1B,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,eAAe,EAAE,SAAS,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../../src/services/types/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAChC,UAAU,EAAE,cAAc,CAAC;IAC3B,YAAY,EAAE,WAAW,CAAC;CAC7B;AACD,MAAM,MAAM,aAAa,GACnB,SAAS,GACT,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,MAAM,GACN,aAAa,CAAC;AAEpB,MAAM,MAAM,SAAS,GACf,QAAQ,GACR,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,QAAQ,CAAC;AAEf,MAAM,WAAW,sBAAsB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IAGd,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IAEzB,qBAAqB,CAAC,EAAE,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,sBAAsB,EAAE,CAAC;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../../src/services/types/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAChC,UAAU,EAAE,cAAc,CAAC;IAC3B,YAAY,EAAE,WAAW,CAAC;CAC7B;AACD,MAAM,MAAM,aAAa,GACnB,SAAS,GACT,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,MAAM,GACN,aAAa,CAAC;AAEpB,MAAM,MAAM,SAAS,GACf,QAAQ,GACR,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,QAAQ,CAAC;AAEf,MAAM,WAAW,sBAAsB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IAGd,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IAEzB,qBAAqB,CAAC,EAAE,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,sBAAsB,EAAE,CAAC;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IAEtB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IAGX,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,6BAA6B,EAAE,MAAM,CAAC;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0BAA0B,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,IAAI,CAAC;CACrB"}
|
package/package.json
CHANGED