@sudobility/contracts 0.14.0 → 0.15.1
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/evm/src/evm/{mailer-client.d.ts → evm-mailer-client.d.ts} +146 -50
- package/dist/evm/src/evm/evm-mailer-client.d.ts.map +1 -0
- package/dist/evm/src/evm/evm-mailer-client.js +924 -0
- package/dist/evm/src/evm/evm-mailer-client.js.map +1 -0
- package/dist/evm/src/evm/index.d.ts +1 -1
- package/dist/evm/src/evm/index.d.ts.map +1 -1
- package/dist/evm/src/evm/index.js +4 -4
- package/dist/evm/src/evm/index.js.map +1 -1
- package/dist/solana/solana/index.d.ts +1 -1
- package/dist/solana/solana/index.d.ts.map +1 -1
- package/dist/solana/solana/index.js +4 -3
- package/dist/solana/solana/index.js.map +1 -1
- package/dist/solana/solana/solana-mailer-client.d.ts +209 -0
- package/dist/solana/solana/solana-mailer-client.d.ts.map +1 -0
- package/dist/solana/solana/solana-mailer-client.js +1004 -0
- package/dist/solana/solana/solana-mailer-client.js.map +1 -0
- package/dist/solana/solana/types.d.ts +3 -2
- package/dist/solana/solana/types.d.ts.map +1 -1
- package/dist/solana/solana/types.js.map +1 -1
- package/dist/{unified-esm/src/evm/mailer-client.d.ts → unified/src/evm/evm-mailer-client.d.ts} +146 -50
- package/dist/unified/src/evm/evm-mailer-client.d.ts.map +1 -0
- package/dist/unified/src/evm/evm-mailer-client.js +924 -0
- package/dist/unified/src/evm/evm-mailer-client.js.map +1 -0
- package/dist/unified/src/evm/index.d.ts +1 -1
- package/dist/unified/src/evm/index.d.ts.map +1 -1
- package/dist/unified/src/evm/index.js +4 -4
- package/dist/unified/src/evm/index.js.map +1 -1
- package/dist/unified/src/react/context/MailerProvider.d.ts +26 -20
- package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
- package/dist/unified/src/react/context/MailerProvider.js +26 -26
- package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
- package/dist/unified/src/react/hooks/useMailerMutations.d.ts +225 -192
- package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
- package/dist/unified/src/react/hooks/useMailerMutations.js +263 -266
- package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
- package/dist/unified/src/react/hooks/useMailerQueries.d.ts +117 -63
- package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
- package/dist/unified/src/react/hooks/useMailerQueries.js +239 -104
- package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
- package/dist/unified/src/react/index.d.ts +5 -3
- package/dist/unified/src/react/index.d.ts.map +1 -1
- package/dist/unified/src/react/index.js +41 -26
- package/dist/unified/src/react/index.js.map +1 -1
- package/dist/unified/src/solana/index.d.ts +1 -1
- package/dist/unified/src/solana/index.d.ts.map +1 -1
- package/dist/unified/src/solana/index.js +4 -3
- package/dist/unified/src/solana/index.js.map +1 -1
- package/dist/unified/src/solana/solana-mailer-client.d.ts +209 -0
- package/dist/unified/src/solana/solana-mailer-client.d.ts.map +1 -0
- package/dist/unified/src/solana/solana-mailer-client.js +1004 -0
- package/dist/unified/src/solana/solana-mailer-client.js.map +1 -0
- package/dist/unified/src/solana/types.d.ts +3 -2
- package/dist/unified/src/solana/types.d.ts.map +1 -1
- package/dist/unified/src/solana/types.js.map +1 -1
- package/dist/unified/src/unified/onchain-mailer-client.d.ts +224 -139
- package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
- package/dist/unified/src/unified/onchain-mailer-client.js +577 -857
- package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
- package/dist/unified/src/unified/types.d.ts +9 -2
- package/dist/unified/src/unified/types.d.ts.map +1 -1
- package/dist/{unified/src/evm/mailer-client.d.ts → unified-esm/src/evm/evm-mailer-client.d.ts} +146 -50
- package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +1 -0
- package/dist/unified-esm/src/evm/evm-mailer-client.js +920 -0
- package/dist/unified-esm/src/evm/evm-mailer-client.js.map +1 -0
- package/dist/unified-esm/src/evm/index.d.ts +1 -1
- package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
- package/dist/unified-esm/src/evm/index.js +2 -2
- package/dist/unified-esm/src/evm/index.js.map +1 -1
- package/dist/unified-esm/src/react/context/MailerProvider.d.ts +26 -20
- package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
- package/dist/unified-esm/src/react/context/MailerProvider.js +25 -26
- package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
- package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +225 -192
- package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
- package/dist/unified-esm/src/react/hooks/useMailerMutations.js +254 -262
- package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
- package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +117 -63
- package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
- package/dist/unified-esm/src/react/hooks/useMailerQueries.js +232 -102
- package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
- package/dist/unified-esm/src/react/index.d.ts +5 -3
- package/dist/unified-esm/src/react/index.d.ts.map +1 -1
- package/dist/unified-esm/src/react/index.js +9 -5
- package/dist/unified-esm/src/react/index.js.map +1 -1
- package/dist/unified-esm/src/solana/index.d.ts +1 -1
- package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
- package/dist/unified-esm/src/solana/index.js +2 -1
- package/dist/unified-esm/src/solana/index.js.map +1 -1
- package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +209 -0
- package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +1 -0
- package/dist/unified-esm/src/solana/solana-mailer-client.js +1000 -0
- package/dist/unified-esm/src/solana/solana-mailer-client.js.map +1 -0
- package/dist/unified-esm/src/solana/types.d.ts +3 -2
- package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
- package/dist/unified-esm/src/solana/types.js.map +1 -1
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +224 -139
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
- package/dist/unified-esm/src/unified/onchain-mailer-client.js +579 -859
- package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
- package/dist/unified-esm/src/unified/types.d.ts +9 -2
- package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/evm/src/evm/mailer-client.d.ts.map +0 -1
- package/dist/evm/src/evm/mailer-client.js +0 -619
- package/dist/evm/src/evm/mailer-client.js.map +0 -1
- package/dist/solana/solana/mailer-client.d.ts +0 -282
- package/dist/solana/solana/mailer-client.d.ts.map +0 -1
- package/dist/solana/solana/mailer-client.js +0 -989
- package/dist/solana/solana/mailer-client.js.map +0 -1
- package/dist/unified/src/evm/mailer-client.d.ts.map +0 -1
- package/dist/unified/src/evm/mailer-client.js +0 -619
- package/dist/unified/src/evm/mailer-client.js.map +0 -1
- package/dist/unified/src/solana/mailer-client.d.ts +0 -282
- package/dist/unified/src/solana/mailer-client.d.ts.map +0 -1
- package/dist/unified/src/solana/mailer-client.js +0 -989
- package/dist/unified/src/solana/mailer-client.js.map +0 -1
- package/dist/unified-esm/src/evm/mailer-client.d.ts.map +0 -1
- package/dist/unified-esm/src/evm/mailer-client.js +0 -615
- package/dist/unified-esm/src/evm/mailer-client.js.map +0 -1
- package/dist/unified-esm/src/solana/mailer-client.d.ts +0 -282
- package/dist/unified-esm/src/solana/mailer-client.d.ts.map +0 -1
- package/dist/unified-esm/src/solana/mailer-client.js +0 -985
- package/dist/unified-esm/src/solana/mailer-client.js.map +0 -1
|
@@ -0,0 +1,1004 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SolanaMailerClient = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
6
|
+
/**
|
|
7
|
+
* Native Solana Program instruction types
|
|
8
|
+
*/
|
|
9
|
+
var InstructionType;
|
|
10
|
+
(function (InstructionType) {
|
|
11
|
+
InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
|
|
12
|
+
InstructionType[InstructionType["Send"] = 1] = "Send";
|
|
13
|
+
InstructionType[InstructionType["SendPrepared"] = 2] = "SendPrepared";
|
|
14
|
+
InstructionType[InstructionType["SendThroughWebhook"] = 3] = "SendThroughWebhook";
|
|
15
|
+
InstructionType[InstructionType["SendToEmail"] = 4] = "SendToEmail";
|
|
16
|
+
InstructionType[InstructionType["SendPreparedToEmail"] = 5] = "SendPreparedToEmail";
|
|
17
|
+
InstructionType[InstructionType["ClaimRecipientShare"] = 6] = "ClaimRecipientShare";
|
|
18
|
+
InstructionType[InstructionType["ClaimOwnerShare"] = 7] = "ClaimOwnerShare";
|
|
19
|
+
InstructionType[InstructionType["ClaimExpiredShares"] = 8] = "ClaimExpiredShares";
|
|
20
|
+
InstructionType[InstructionType["SetFees"] = 9] = "SetFees";
|
|
21
|
+
InstructionType[InstructionType["DelegateTo"] = 10] = "DelegateTo";
|
|
22
|
+
InstructionType[InstructionType["RejectDelegation"] = 11] = "RejectDelegation";
|
|
23
|
+
InstructionType[InstructionType["SetCustomFeePercentage"] = 12] = "SetCustomFeePercentage";
|
|
24
|
+
InstructionType[InstructionType["ClearCustomFeePercentage"] = 13] = "ClearCustomFeePercentage";
|
|
25
|
+
InstructionType[InstructionType["Pause"] = 14] = "Pause";
|
|
26
|
+
InstructionType[InstructionType["Unpause"] = 15] = "Unpause";
|
|
27
|
+
InstructionType[InstructionType["EmergencyUnpause"] = 16] = "EmergencyUnpause";
|
|
28
|
+
InstructionType[InstructionType["DistributeClaimableFunds"] = 17] = "DistributeClaimableFunds";
|
|
29
|
+
})(InstructionType || (InstructionType = {}));
|
|
30
|
+
// Instruction data encoding functions
|
|
31
|
+
function encodeInitialize(usdcMint) {
|
|
32
|
+
const data = Buffer.alloc(1 + 32);
|
|
33
|
+
data.writeUInt8(InstructionType.Initialize, 0);
|
|
34
|
+
usdcMint.toBuffer().copy(data, 1);
|
|
35
|
+
return data;
|
|
36
|
+
}
|
|
37
|
+
function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToName = false) {
|
|
38
|
+
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
39
|
+
const bodyBytes = Buffer.from(body, 'utf8');
|
|
40
|
+
const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 1 + 1);
|
|
41
|
+
let offset = 0;
|
|
42
|
+
data.writeUInt8(InstructionType.Send, offset);
|
|
43
|
+
offset += 1;
|
|
44
|
+
to.toBuffer().copy(data, offset);
|
|
45
|
+
offset += 32;
|
|
46
|
+
data.writeUInt32LE(subjectBytes.length, offset);
|
|
47
|
+
offset += 4;
|
|
48
|
+
subjectBytes.copy(data, offset);
|
|
49
|
+
offset += subjectBytes.length;
|
|
50
|
+
data.writeUInt32LE(bodyBytes.length, offset);
|
|
51
|
+
offset += 4;
|
|
52
|
+
bodyBytes.copy(data, offset);
|
|
53
|
+
offset += bodyBytes.length;
|
|
54
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
55
|
+
offset += 1;
|
|
56
|
+
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
57
|
+
return data;
|
|
58
|
+
}
|
|
59
|
+
function encodeSendPrepared(to, mailId, revenueShareToReceiver, resolveSenderToName = false) {
|
|
60
|
+
const mailIdBytes = Buffer.from(mailId, 'utf8');
|
|
61
|
+
const data = Buffer.alloc(1 + 32 + 4 + mailIdBytes.length + 1 + 1);
|
|
62
|
+
let offset = 0;
|
|
63
|
+
data.writeUInt8(InstructionType.SendPrepared, offset);
|
|
64
|
+
offset += 1;
|
|
65
|
+
to.toBuffer().copy(data, offset);
|
|
66
|
+
offset += 32;
|
|
67
|
+
data.writeUInt32LE(mailIdBytes.length, offset);
|
|
68
|
+
offset += 4;
|
|
69
|
+
mailIdBytes.copy(data, offset);
|
|
70
|
+
offset += mailIdBytes.length;
|
|
71
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
72
|
+
offset += 1;
|
|
73
|
+
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
function encodeSendThroughWebhook(to, subject, body, webhookId, revenueShareToReceiver) {
|
|
77
|
+
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
78
|
+
const bodyBytes = Buffer.from(body, 'utf8');
|
|
79
|
+
const webhookIdBytes = Buffer.from(webhookId, 'utf8');
|
|
80
|
+
const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 4 + webhookIdBytes.length + 1);
|
|
81
|
+
let offset = 0;
|
|
82
|
+
data.writeUInt8(InstructionType.SendThroughWebhook, offset);
|
|
83
|
+
offset += 1;
|
|
84
|
+
to.toBuffer().copy(data, offset);
|
|
85
|
+
offset += 32;
|
|
86
|
+
data.writeUInt32LE(subjectBytes.length, offset);
|
|
87
|
+
offset += 4;
|
|
88
|
+
subjectBytes.copy(data, offset);
|
|
89
|
+
offset += subjectBytes.length;
|
|
90
|
+
data.writeUInt32LE(bodyBytes.length, offset);
|
|
91
|
+
offset += 4;
|
|
92
|
+
bodyBytes.copy(data, offset);
|
|
93
|
+
offset += bodyBytes.length;
|
|
94
|
+
data.writeUInt32LE(webhookIdBytes.length, offset);
|
|
95
|
+
offset += 4;
|
|
96
|
+
webhookIdBytes.copy(data, offset);
|
|
97
|
+
offset += webhookIdBytes.length;
|
|
98
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
99
|
+
return data;
|
|
100
|
+
}
|
|
101
|
+
function encodeSendToEmail(emailHash, subject, body, payer, revenueShareToReceiver) {
|
|
102
|
+
const emailHashBytes = Buffer.from(emailHash, 'utf8');
|
|
103
|
+
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
104
|
+
const bodyBytes = Buffer.from(body, 'utf8');
|
|
105
|
+
const data = Buffer.alloc(1 + 4 + emailHashBytes.length + 4 + subjectBytes.length + 4 + bodyBytes.length + 32 + 1);
|
|
106
|
+
let offset = 0;
|
|
107
|
+
data.writeUInt8(InstructionType.SendToEmail, offset);
|
|
108
|
+
offset += 1;
|
|
109
|
+
data.writeUInt32LE(emailHashBytes.length, offset);
|
|
110
|
+
offset += 4;
|
|
111
|
+
emailHashBytes.copy(data, offset);
|
|
112
|
+
offset += emailHashBytes.length;
|
|
113
|
+
data.writeUInt32LE(subjectBytes.length, offset);
|
|
114
|
+
offset += 4;
|
|
115
|
+
subjectBytes.copy(data, offset);
|
|
116
|
+
offset += subjectBytes.length;
|
|
117
|
+
data.writeUInt32LE(bodyBytes.length, offset);
|
|
118
|
+
offset += 4;
|
|
119
|
+
bodyBytes.copy(data, offset);
|
|
120
|
+
offset += bodyBytes.length;
|
|
121
|
+
payer.toBuffer().copy(data, offset);
|
|
122
|
+
offset += 32;
|
|
123
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
124
|
+
return data;
|
|
125
|
+
}
|
|
126
|
+
function encodeSendPreparedToEmail(emailHash, mailId, payer, revenueShareToReceiver) {
|
|
127
|
+
const emailHashBytes = Buffer.from(emailHash, 'utf8');
|
|
128
|
+
const mailIdBytes = Buffer.from(mailId, 'utf8');
|
|
129
|
+
const data = Buffer.alloc(1 + 4 + emailHashBytes.length + 4 + mailIdBytes.length + 32 + 1);
|
|
130
|
+
let offset = 0;
|
|
131
|
+
data.writeUInt8(InstructionType.SendPreparedToEmail, offset);
|
|
132
|
+
offset += 1;
|
|
133
|
+
data.writeUInt32LE(emailHashBytes.length, offset);
|
|
134
|
+
offset += 4;
|
|
135
|
+
emailHashBytes.copy(data, offset);
|
|
136
|
+
offset += emailHashBytes.length;
|
|
137
|
+
data.writeUInt32LE(mailIdBytes.length, offset);
|
|
138
|
+
offset += 4;
|
|
139
|
+
mailIdBytes.copy(data, offset);
|
|
140
|
+
offset += mailIdBytes.length;
|
|
141
|
+
payer.toBuffer().copy(data, offset);
|
|
142
|
+
offset += 32;
|
|
143
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
144
|
+
return data;
|
|
145
|
+
}
|
|
146
|
+
function encodeSetFees(sendFee, delegationFee) {
|
|
147
|
+
const data = Buffer.alloc(1 + 8 + 8);
|
|
148
|
+
data.writeUInt8(InstructionType.SetFees, 0);
|
|
149
|
+
data.writeBigUInt64LE(sendFee, 1);
|
|
150
|
+
data.writeBigUInt64LE(delegationFee, 9);
|
|
151
|
+
return data;
|
|
152
|
+
}
|
|
153
|
+
function encodeDelegateTo(delegate) {
|
|
154
|
+
const data = Buffer.alloc(1 + 1 + (delegate ? 32 : 0));
|
|
155
|
+
data.writeUInt8(InstructionType.DelegateTo, 0);
|
|
156
|
+
data.writeUInt8(delegate ? 1 : 0, 1);
|
|
157
|
+
if (delegate) {
|
|
158
|
+
delegate.toBuffer().copy(data, 2);
|
|
159
|
+
}
|
|
160
|
+
return data;
|
|
161
|
+
}
|
|
162
|
+
function encodeRejectDelegation(delegatingAddress) {
|
|
163
|
+
const data = Buffer.alloc(1 + 32);
|
|
164
|
+
data.writeUInt8(InstructionType.RejectDelegation, 0);
|
|
165
|
+
delegatingAddress.toBuffer().copy(data, 1);
|
|
166
|
+
return data;
|
|
167
|
+
}
|
|
168
|
+
function encodeSetCustomFeePercentage(account, percentage) {
|
|
169
|
+
if (percentage < 0 || percentage > 100) {
|
|
170
|
+
throw new Error('Percentage must be between 0 and 100');
|
|
171
|
+
}
|
|
172
|
+
const data = Buffer.alloc(1 + 32 + 1);
|
|
173
|
+
data.writeUInt8(InstructionType.SetCustomFeePercentage, 0);
|
|
174
|
+
account.toBuffer().copy(data, 1);
|
|
175
|
+
data.writeUInt8(percentage, 33);
|
|
176
|
+
return data;
|
|
177
|
+
}
|
|
178
|
+
function encodeClearCustomFeePercentage(account) {
|
|
179
|
+
const data = Buffer.alloc(1 + 32);
|
|
180
|
+
data.writeUInt8(InstructionType.ClearCustomFeePercentage, 0);
|
|
181
|
+
account.toBuffer().copy(data, 1);
|
|
182
|
+
return data;
|
|
183
|
+
}
|
|
184
|
+
function encodeClaimExpiredShares(recipient) {
|
|
185
|
+
const data = Buffer.alloc(1 + 32);
|
|
186
|
+
data.writeUInt8(InstructionType.ClaimExpiredShares, 0);
|
|
187
|
+
recipient.toBuffer().copy(data, 1);
|
|
188
|
+
return data;
|
|
189
|
+
}
|
|
190
|
+
function encodeDistributeClaimableFunds(recipients) {
|
|
191
|
+
const recipientCount = recipients.length;
|
|
192
|
+
const data = Buffer.alloc(1 + 4 + recipientCount * 32);
|
|
193
|
+
let offset = 0;
|
|
194
|
+
data.writeUInt8(InstructionType.DistributeClaimableFunds, offset);
|
|
195
|
+
offset += 1;
|
|
196
|
+
data.writeUInt32LE(recipientCount, offset);
|
|
197
|
+
offset += 4;
|
|
198
|
+
for (const recipient of recipients) {
|
|
199
|
+
recipient.toBuffer().copy(data, offset);
|
|
200
|
+
offset += 32;
|
|
201
|
+
}
|
|
202
|
+
return data;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Stateless Solana Mailer client.
|
|
206
|
+
* All methods take wallet and chainInfo as parameters.
|
|
207
|
+
* No state is stored in the instance.
|
|
208
|
+
*/
|
|
209
|
+
class SolanaMailerClient {
|
|
210
|
+
constructor() {
|
|
211
|
+
this.defaultComputeUnitMultiplier = 1.2; // 20% buffer by default
|
|
212
|
+
// Default compute unit limits for common operations
|
|
213
|
+
this.defaultComputeUnits = {
|
|
214
|
+
send: 200000,
|
|
215
|
+
sendPrepared: 150000,
|
|
216
|
+
sendToEmail: 250000,
|
|
217
|
+
claimRevenue: 100000,
|
|
218
|
+
claimOwnerShare: 100000,
|
|
219
|
+
delegateTo: 80000,
|
|
220
|
+
setFees: 60000,
|
|
221
|
+
pause: 50000,
|
|
222
|
+
unpause: 50000,
|
|
223
|
+
initialize: 100000,
|
|
224
|
+
distributeClaimableFunds: 150000,
|
|
225
|
+
};
|
|
226
|
+
// Priority fee recommendations based on network congestion
|
|
227
|
+
this.priorityFeeRecommendations = {
|
|
228
|
+
low: 1000, // 1,000 microLamports - for low priority transactions
|
|
229
|
+
normal: 10000, // 10,000 microLamports - for normal priority
|
|
230
|
+
high: 50000, // 50,000 microLamports - for high priority
|
|
231
|
+
urgent: 100000, // 100,000 microLamports - for urgent transactions
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Create or get connection from wallet/chainInfo
|
|
236
|
+
*/
|
|
237
|
+
async getOrCreateConnection(chainInfo, connection) {
|
|
238
|
+
if (connection) {
|
|
239
|
+
return connection;
|
|
240
|
+
}
|
|
241
|
+
// Build RPC URL from ChainInfo
|
|
242
|
+
let rpcUrl;
|
|
243
|
+
if (chainInfo.alchemyNetwork) {
|
|
244
|
+
rpcUrl = `https://${chainInfo.alchemyNetwork}.g.alchemy.com/v2/demo`;
|
|
245
|
+
}
|
|
246
|
+
else if (chainInfo.ankrNetwork) {
|
|
247
|
+
rpcUrl = `https://rpc.ankr.com/${chainInfo.ankrNetwork}`;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// Default Solana endpoints
|
|
251
|
+
rpcUrl = chainInfo.isDev
|
|
252
|
+
? 'https://api.devnet.solana.com'
|
|
253
|
+
: 'https://api.mainnet-beta.solana.com';
|
|
254
|
+
}
|
|
255
|
+
return new web3_js_1.Connection(rpcUrl, 'confirmed');
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Get program and state PDAs from chainInfo
|
|
259
|
+
*/
|
|
260
|
+
getProgramAddresses(chainInfo) {
|
|
261
|
+
if (!chainInfo.mailerAddress) {
|
|
262
|
+
throw new Error(`No mailer program deployed on ${chainInfo.name}`);
|
|
263
|
+
}
|
|
264
|
+
const programId = new web3_js_1.PublicKey(chainInfo.mailerAddress);
|
|
265
|
+
const [mailerPda, bump] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('mailer')], programId);
|
|
266
|
+
return {
|
|
267
|
+
programId,
|
|
268
|
+
mailerStatePda: mailerPda,
|
|
269
|
+
mailerBump: bump,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Optimize compute units for a transaction
|
|
274
|
+
*/
|
|
275
|
+
async optimizeComputeUnits(transaction, wallet, connection, options, defaultComputeUnits) {
|
|
276
|
+
// Skip if explicitly disabled
|
|
277
|
+
if (options?.skipComputeUnits) {
|
|
278
|
+
return { transaction };
|
|
279
|
+
}
|
|
280
|
+
let simulatedUnits;
|
|
281
|
+
let computeUnitLimit = options?.computeUnitLimit;
|
|
282
|
+
// Auto-optimize by simulating transaction
|
|
283
|
+
if (options?.autoOptimize && !computeUnitLimit) {
|
|
284
|
+
let retryCount = 0;
|
|
285
|
+
const maxRetries = 2;
|
|
286
|
+
while (retryCount <= maxRetries) {
|
|
287
|
+
try {
|
|
288
|
+
// Set a high limit for simulation
|
|
289
|
+
const simTransaction = new web3_js_1.Transaction().add(...transaction.instructions);
|
|
290
|
+
simTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
291
|
+
units: 1400000, // Max for simulation
|
|
292
|
+
}));
|
|
293
|
+
simTransaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
294
|
+
simTransaction.feePayer = wallet.publicKey;
|
|
295
|
+
const simulation = await connection.simulateTransaction(simTransaction);
|
|
296
|
+
if (simulation.value.err === null && simulation.value.unitsConsumed) {
|
|
297
|
+
simulatedUnits = simulation.value.unitsConsumed;
|
|
298
|
+
const multiplier = options.computeUnitMultiplier ?? this.defaultComputeUnitMultiplier;
|
|
299
|
+
computeUnitLimit = Math.min(Math.ceil(simulatedUnits * multiplier), 1400000);
|
|
300
|
+
break; // Success
|
|
301
|
+
}
|
|
302
|
+
else if (simulation.value.err) {
|
|
303
|
+
throw new Error(`Simulation failed: ${JSON.stringify(simulation.value.err)}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
retryCount++;
|
|
308
|
+
if (retryCount > maxRetries) {
|
|
309
|
+
console.warn(`Failed to auto-optimize compute units after ${maxRetries} retries:`, error);
|
|
310
|
+
// Use default if provided
|
|
311
|
+
if (defaultComputeUnits) {
|
|
312
|
+
computeUnitLimit = defaultComputeUnits;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// Wait before retry
|
|
317
|
+
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Use default compute units if no limit is set yet
|
|
323
|
+
if (!computeUnitLimit && defaultComputeUnits) {
|
|
324
|
+
computeUnitLimit = defaultComputeUnits;
|
|
325
|
+
}
|
|
326
|
+
// Apply compute budget instructions
|
|
327
|
+
const optimizedTx = new web3_js_1.Transaction();
|
|
328
|
+
// Add compute unit limit if specified
|
|
329
|
+
if (computeUnitLimit) {
|
|
330
|
+
optimizedTx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
331
|
+
units: computeUnitLimit,
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
// Add priority fee if specified (or use recommended normal priority)
|
|
335
|
+
const priorityFee = options?.computeUnitPrice ??
|
|
336
|
+
(options?.autoOptimize ? this.priorityFeeRecommendations.normal : undefined);
|
|
337
|
+
if (priorityFee) {
|
|
338
|
+
optimizedTx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
339
|
+
microLamports: priorityFee,
|
|
340
|
+
}));
|
|
341
|
+
}
|
|
342
|
+
// Add original instructions
|
|
343
|
+
optimizedTx.add(...transaction.instructions);
|
|
344
|
+
return {
|
|
345
|
+
transaction: optimizedTx,
|
|
346
|
+
simulatedUnits,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Send and confirm transaction
|
|
351
|
+
*/
|
|
352
|
+
async sendTransaction(transaction, wallet, connection, options, computeOptions, defaultComputeUnits) {
|
|
353
|
+
// Optimize compute units
|
|
354
|
+
const { transaction: optimizedTx, simulatedUnits } = await this.optimizeComputeUnits(transaction, wallet, connection, computeOptions, defaultComputeUnits);
|
|
355
|
+
// Get latest blockhash
|
|
356
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
357
|
+
optimizedTx.recentBlockhash = blockhash;
|
|
358
|
+
optimizedTx.feePayer = wallet.publicKey;
|
|
359
|
+
// Sign transaction
|
|
360
|
+
const signed = await wallet.signTransaction(optimizedTx);
|
|
361
|
+
// Send and confirm
|
|
362
|
+
const signature = await connection.sendRawTransaction(signed.serialize(), {
|
|
363
|
+
skipPreflight: options?.skipPreflight ?? false,
|
|
364
|
+
preflightCommitment: options?.preflightCommitment ?? 'confirmed',
|
|
365
|
+
});
|
|
366
|
+
await connection.confirmTransaction(signature, options?.commitment ?? 'confirmed');
|
|
367
|
+
return {
|
|
368
|
+
signature,
|
|
369
|
+
transactionHash: signature,
|
|
370
|
+
simulatedUnits,
|
|
371
|
+
computeUnitLimit: computeOptions?.computeUnitLimit,
|
|
372
|
+
computeUnitPrice: computeOptions?.computeUnitPrice,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Initialize the mailer program (owner only)
|
|
377
|
+
*/
|
|
378
|
+
async initialize(connectedWallet, chainInfo, computeOptions) {
|
|
379
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
380
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
381
|
+
if (!chainInfo.usdcAddress) {
|
|
382
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
383
|
+
}
|
|
384
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
385
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
386
|
+
programId,
|
|
387
|
+
keys: [
|
|
388
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
389
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
390
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
391
|
+
],
|
|
392
|
+
data: encodeInitialize(usdcMint),
|
|
393
|
+
});
|
|
394
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
395
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Send a message with optional revenue sharing
|
|
399
|
+
*/
|
|
400
|
+
async send(connectedWallet, chainInfo, to, subject, body, revenueShareToReceiver, computeOptions) {
|
|
401
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
402
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
403
|
+
if (!chainInfo.usdcAddress) {
|
|
404
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
405
|
+
}
|
|
406
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
407
|
+
const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
|
|
408
|
+
// Get token accounts
|
|
409
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
410
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
411
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
|
|
412
|
+
const keys = [
|
|
413
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
414
|
+
{ pubkey: toPubkey, isSigner: false, isWritable: false },
|
|
415
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
416
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
417
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
418
|
+
{ pubkey: recipientInfo, isSigner: false, isWritable: true },
|
|
419
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
420
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
421
|
+
];
|
|
422
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
423
|
+
programId,
|
|
424
|
+
keys,
|
|
425
|
+
data: encodeSend(toPubkey, subject, body, revenueShareToReceiver),
|
|
426
|
+
});
|
|
427
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
428
|
+
// Check if mailer token account exists, create if not
|
|
429
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
430
|
+
if (!accountInfo) {
|
|
431
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
432
|
+
}
|
|
433
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Send a prepared message
|
|
437
|
+
*/
|
|
438
|
+
async sendPrepared(connectedWallet, chainInfo, to, mailId, revenueShareToReceiver, computeOptions) {
|
|
439
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
440
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
441
|
+
if (!chainInfo.usdcAddress) {
|
|
442
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
443
|
+
}
|
|
444
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
445
|
+
const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
|
|
446
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
447
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
448
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
|
|
449
|
+
const keys = [
|
|
450
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
451
|
+
{ pubkey: toPubkey, isSigner: false, isWritable: false },
|
|
452
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
453
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
454
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
455
|
+
{ pubkey: recipientInfo, isSigner: false, isWritable: true },
|
|
456
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
457
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
458
|
+
];
|
|
459
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
460
|
+
programId,
|
|
461
|
+
keys,
|
|
462
|
+
data: encodeSendPrepared(toPubkey, mailId, revenueShareToReceiver),
|
|
463
|
+
});
|
|
464
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
465
|
+
// Check if mailer token account exists, create if not
|
|
466
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
467
|
+
if (!accountInfo) {
|
|
468
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
469
|
+
}
|
|
470
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Send through webhook
|
|
474
|
+
*/
|
|
475
|
+
async sendThroughWebhook(connectedWallet, chainInfo, to, subject, body, webhookId, revenueShareToReceiver, computeOptions) {
|
|
476
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
477
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
478
|
+
if (!chainInfo.usdcAddress) {
|
|
479
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
480
|
+
}
|
|
481
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
482
|
+
const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
|
|
483
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
484
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
485
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
|
|
486
|
+
const keys = [
|
|
487
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
488
|
+
{ pubkey: toPubkey, isSigner: false, isWritable: false },
|
|
489
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
490
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
491
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
492
|
+
{ pubkey: recipientInfo, isSigner: false, isWritable: true },
|
|
493
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
494
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
495
|
+
];
|
|
496
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
497
|
+
programId,
|
|
498
|
+
keys,
|
|
499
|
+
data: encodeSendThroughWebhook(toPubkey, subject, body, webhookId, revenueShareToReceiver),
|
|
500
|
+
});
|
|
501
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
502
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
503
|
+
if (!accountInfo) {
|
|
504
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
505
|
+
}
|
|
506
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Send to email address
|
|
510
|
+
*/
|
|
511
|
+
async sendToEmail(emailHash, subject, body, payer, revenueShareToReceiver, connectedWallet, chainInfo, computeOptions) {
|
|
512
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
513
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
514
|
+
if (!chainInfo.usdcAddress) {
|
|
515
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
516
|
+
}
|
|
517
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
518
|
+
const payerPubkey = typeof payer === 'string' ? new web3_js_1.PublicKey(payer) : payer;
|
|
519
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
520
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
521
|
+
const keys = [
|
|
522
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
523
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
524
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
525
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
526
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
527
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
528
|
+
];
|
|
529
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
530
|
+
programId,
|
|
531
|
+
keys,
|
|
532
|
+
data: encodeSendToEmail(emailHash, subject, body, payerPubkey, revenueShareToReceiver),
|
|
533
|
+
});
|
|
534
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
535
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
536
|
+
if (!accountInfo) {
|
|
537
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
538
|
+
}
|
|
539
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Send prepared to email address
|
|
543
|
+
*/
|
|
544
|
+
async sendPreparedToEmail(emailHash, mailId, payer, revenueShareToReceiver, connectedWallet, chainInfo, computeOptions) {
|
|
545
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
546
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
547
|
+
if (!chainInfo.usdcAddress) {
|
|
548
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
549
|
+
}
|
|
550
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
551
|
+
const payerPubkey = typeof payer === 'string' ? new web3_js_1.PublicKey(payer) : payer;
|
|
552
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
553
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
554
|
+
const keys = [
|
|
555
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
556
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
557
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
558
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
559
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
560
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
561
|
+
];
|
|
562
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
563
|
+
programId,
|
|
564
|
+
keys,
|
|
565
|
+
data: encodeSendPreparedToEmail(emailHash, mailId, payerPubkey, revenueShareToReceiver),
|
|
566
|
+
});
|
|
567
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
568
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
569
|
+
if (!accountInfo) {
|
|
570
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
571
|
+
}
|
|
572
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Claim recipient share
|
|
576
|
+
*/
|
|
577
|
+
async claimRecipientShare(connectedWallet, chainInfo, computeOptions) {
|
|
578
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
579
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
580
|
+
if (!chainInfo.usdcAddress) {
|
|
581
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
582
|
+
}
|
|
583
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
584
|
+
const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
585
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
586
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), connectedWallet.wallet.publicKey.toBuffer()], programId);
|
|
587
|
+
const keys = [
|
|
588
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
589
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
590
|
+
{ pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
|
|
591
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
592
|
+
{ pubkey: recipientInfo, isSigner: false, isWritable: true },
|
|
593
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
594
|
+
];
|
|
595
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
596
|
+
programId,
|
|
597
|
+
keys,
|
|
598
|
+
data: Buffer.from([InstructionType.ClaimRecipientShare]),
|
|
599
|
+
});
|
|
600
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
601
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Claim owner share (owner only)
|
|
605
|
+
*/
|
|
606
|
+
async claimOwnerShare(connectedWallet, chainInfo, computeOptions) {
|
|
607
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
608
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
609
|
+
if (!chainInfo.usdcAddress) {
|
|
610
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
611
|
+
}
|
|
612
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
613
|
+
const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
614
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
615
|
+
const keys = [
|
|
616
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
617
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
618
|
+
{ pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
|
|
619
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
620
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
621
|
+
];
|
|
622
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
623
|
+
programId,
|
|
624
|
+
keys,
|
|
625
|
+
data: Buffer.from([InstructionType.ClaimOwnerShare]),
|
|
626
|
+
});
|
|
627
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
628
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Claim expired shares (owner only)
|
|
632
|
+
*/
|
|
633
|
+
async claimExpiredShares(connectedWallet, chainInfo, recipient, computeOptions) {
|
|
634
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
635
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
636
|
+
const recipientPubkey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
|
|
637
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipientPubkey.toBuffer()], programId);
|
|
638
|
+
const keys = [
|
|
639
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
640
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
641
|
+
{ pubkey: recipientInfo, isSigner: false, isWritable: true },
|
|
642
|
+
];
|
|
643
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
644
|
+
programId,
|
|
645
|
+
keys,
|
|
646
|
+
data: encodeClaimExpiredShares(recipientPubkey),
|
|
647
|
+
});
|
|
648
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
649
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Delegate to another address
|
|
653
|
+
*/
|
|
654
|
+
async delegateTo(connectedWallet, chainInfo, delegate, computeOptions) {
|
|
655
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
656
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
657
|
+
if (!chainInfo.usdcAddress) {
|
|
658
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
659
|
+
}
|
|
660
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
661
|
+
const delegatePubkey = delegate
|
|
662
|
+
? (typeof delegate === 'string' ? new web3_js_1.PublicKey(delegate) : delegate)
|
|
663
|
+
: null;
|
|
664
|
+
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
665
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
666
|
+
const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), connectedWallet.wallet.publicKey.toBuffer()], programId);
|
|
667
|
+
const keys = [
|
|
668
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
669
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
670
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
671
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
672
|
+
{ pubkey: delegatorInfo, isSigner: false, isWritable: true },
|
|
673
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
674
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
675
|
+
];
|
|
676
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
677
|
+
programId,
|
|
678
|
+
keys,
|
|
679
|
+
data: encodeDelegateTo(delegatePubkey),
|
|
680
|
+
});
|
|
681
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
682
|
+
const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
|
|
683
|
+
if (!accountInfo) {
|
|
684
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
|
|
685
|
+
}
|
|
686
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Reject delegation
|
|
690
|
+
*/
|
|
691
|
+
async rejectDelegation(connectedWallet, chainInfo, delegatingAddress, computeOptions) {
|
|
692
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
693
|
+
const { programId } = this.getProgramAddresses(chainInfo);
|
|
694
|
+
const delegatorPubkey = typeof delegatingAddress === 'string' ? new web3_js_1.PublicKey(delegatingAddress) : delegatingAddress;
|
|
695
|
+
const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), delegatorPubkey.toBuffer()], programId);
|
|
696
|
+
const keys = [
|
|
697
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
698
|
+
{ pubkey: delegatorInfo, isSigner: false, isWritable: true },
|
|
699
|
+
];
|
|
700
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
701
|
+
programId,
|
|
702
|
+
keys,
|
|
703
|
+
data: encodeRejectDelegation(delegatorPubkey),
|
|
704
|
+
});
|
|
705
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
706
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Set fees (owner only)
|
|
710
|
+
*/
|
|
711
|
+
async setFees(connectedWallet, chainInfo, sendFee, delegationFee, computeOptions) {
|
|
712
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
713
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
714
|
+
const keys = [
|
|
715
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
716
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
717
|
+
];
|
|
718
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
719
|
+
programId,
|
|
720
|
+
keys,
|
|
721
|
+
data: encodeSetFees(BigInt(sendFee), BigInt(delegationFee)),
|
|
722
|
+
});
|
|
723
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
724
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Set custom fee percentage
|
|
728
|
+
*/
|
|
729
|
+
async setCustomFeePercentage(account, percentage, connectedWallet, chainInfo, computeOptions) {
|
|
730
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
731
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
732
|
+
const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
|
|
733
|
+
const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
|
|
734
|
+
const keys = [
|
|
735
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
|
|
736
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: false },
|
|
737
|
+
{ pubkey: customFeeInfo, isSigner: false, isWritable: true },
|
|
738
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
739
|
+
];
|
|
740
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
741
|
+
programId,
|
|
742
|
+
keys,
|
|
743
|
+
data: encodeSetCustomFeePercentage(accountPubkey, percentage),
|
|
744
|
+
});
|
|
745
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
746
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Clear custom fee percentage
|
|
750
|
+
*/
|
|
751
|
+
async clearCustomFeePercentage(account, connectedWallet, chainInfo, computeOptions) {
|
|
752
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
753
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
754
|
+
const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
|
|
755
|
+
const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
|
|
756
|
+
const keys = [
|
|
757
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
758
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: false },
|
|
759
|
+
{ pubkey: customFeeInfo, isSigner: false, isWritable: true },
|
|
760
|
+
];
|
|
761
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
762
|
+
programId,
|
|
763
|
+
keys,
|
|
764
|
+
data: encodeClearCustomFeePercentage(accountPubkey),
|
|
765
|
+
});
|
|
766
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
767
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Pause the program (owner only)
|
|
771
|
+
*/
|
|
772
|
+
async pause(connectedWallet, chainInfo, computeOptions) {
|
|
773
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
774
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
775
|
+
const keys = [
|
|
776
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
777
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
778
|
+
];
|
|
779
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
780
|
+
programId,
|
|
781
|
+
keys,
|
|
782
|
+
data: Buffer.from([InstructionType.Pause]),
|
|
783
|
+
});
|
|
784
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
785
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Unpause the program (owner only)
|
|
789
|
+
*/
|
|
790
|
+
async unpause(connectedWallet, chainInfo, computeOptions) {
|
|
791
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
792
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
793
|
+
const keys = [
|
|
794
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
795
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
796
|
+
];
|
|
797
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
798
|
+
programId,
|
|
799
|
+
keys,
|
|
800
|
+
data: Buffer.from([InstructionType.Unpause]),
|
|
801
|
+
});
|
|
802
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
803
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Emergency unpause (owner only)
|
|
807
|
+
*/
|
|
808
|
+
async emergencyUnpause(connectedWallet, chainInfo, computeOptions) {
|
|
809
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
810
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
811
|
+
const keys = [
|
|
812
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
813
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
814
|
+
];
|
|
815
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
816
|
+
programId,
|
|
817
|
+
keys,
|
|
818
|
+
data: Buffer.from([InstructionType.EmergencyUnpause]),
|
|
819
|
+
});
|
|
820
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
821
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Distribute claimable funds when paused
|
|
825
|
+
*/
|
|
826
|
+
async distributeClaimableFunds(connectedWallet, chainInfo, recipients, computeOptions) {
|
|
827
|
+
const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
|
|
828
|
+
const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
829
|
+
if (!chainInfo.usdcAddress) {
|
|
830
|
+
throw new Error(`No USDC mint configured for ${chainInfo.name}`);
|
|
831
|
+
}
|
|
832
|
+
const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
|
|
833
|
+
const recipientPubkeys = recipients.map(r => typeof r === 'string' ? new web3_js_1.PublicKey(r) : r);
|
|
834
|
+
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
835
|
+
// Build keys array
|
|
836
|
+
const keys = [
|
|
837
|
+
{ pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
|
|
838
|
+
{ pubkey: mailerStatePda, isSigner: false, isWritable: true },
|
|
839
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
840
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
841
|
+
];
|
|
842
|
+
// Add recipient info and token accounts
|
|
843
|
+
for (const recipient of recipientPubkeys) {
|
|
844
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipient.toBuffer()], programId);
|
|
845
|
+
const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, recipient, false, spl_token_1.TOKEN_PROGRAM_ID);
|
|
846
|
+
keys.push({ pubkey: recipientInfo, isSigner: false, isWritable: true });
|
|
847
|
+
keys.push({ pubkey: recipientTokenAccount, isSigner: false, isWritable: true });
|
|
848
|
+
}
|
|
849
|
+
const instruction = new web3_js_1.TransactionInstruction({
|
|
850
|
+
programId,
|
|
851
|
+
keys,
|
|
852
|
+
data: encodeDistributeClaimableFunds(recipientPubkeys),
|
|
853
|
+
});
|
|
854
|
+
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
855
|
+
return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
|
|
856
|
+
}
|
|
857
|
+
// ============= Read Methods =============
|
|
858
|
+
/**
|
|
859
|
+
* Get fees configuration
|
|
860
|
+
*/
|
|
861
|
+
async getFees(chainInfo, connection) {
|
|
862
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
863
|
+
const { mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
864
|
+
const accountInfo = await conn.getAccountInfo(mailerStatePda);
|
|
865
|
+
if (!accountInfo || !accountInfo.data) {
|
|
866
|
+
throw new Error('Mailer not initialized');
|
|
867
|
+
}
|
|
868
|
+
// Parse the state data
|
|
869
|
+
const data = accountInfo.data;
|
|
870
|
+
const sendFee = data.readBigUInt64LE(41); // After discriminator(8) + owner(32) + paused(1)
|
|
871
|
+
const delegationFee = data.readBigUInt64LE(49);
|
|
872
|
+
return {
|
|
873
|
+
sendFee,
|
|
874
|
+
delegationFee,
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Get send fee only
|
|
879
|
+
*/
|
|
880
|
+
async getSendFee(chainInfo, connection) {
|
|
881
|
+
const fees = await this.getFees(chainInfo, connection);
|
|
882
|
+
return fees.sendFee;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Get delegation fee only
|
|
886
|
+
*/
|
|
887
|
+
async getDelegationFee(chainInfo, connection) {
|
|
888
|
+
const fees = await this.getFees(chainInfo, connection);
|
|
889
|
+
return fees.delegationFee;
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Get recipient claimable info
|
|
893
|
+
*/
|
|
894
|
+
async getRecipientClaimable(recipient, chainInfo, connection) {
|
|
895
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
896
|
+
const { programId } = this.getProgramAddresses(chainInfo);
|
|
897
|
+
const recipientPubkey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
|
|
898
|
+
const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipientPubkey.toBuffer()], programId);
|
|
899
|
+
const accountInfo = await conn.getAccountInfo(recipientInfo);
|
|
900
|
+
if (!accountInfo || !accountInfo.data) {
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
// Parse the recipient info data
|
|
904
|
+
const data = accountInfo.data;
|
|
905
|
+
const amount = data.readBigUInt64LE(8); // After discriminator
|
|
906
|
+
const expiresAt = data.readBigInt64LE(16);
|
|
907
|
+
// Check if expired
|
|
908
|
+
const now = Math.floor(Date.now() / 1000);
|
|
909
|
+
const isExpired = Number(expiresAt) > 0 && Number(expiresAt) < now;
|
|
910
|
+
return {
|
|
911
|
+
amount: Number(amount),
|
|
912
|
+
timestamp: Number(expiresAt), // Using expiresAt as timestamp
|
|
913
|
+
expiresAt: Number(expiresAt),
|
|
914
|
+
recipient: recipient instanceof web3_js_1.PublicKey ? recipient.toBase58() : recipient,
|
|
915
|
+
isExpired,
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Get owner claimable amount
|
|
920
|
+
*/
|
|
921
|
+
async getOwnerClaimable(chainInfo, connection) {
|
|
922
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
923
|
+
const { mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
924
|
+
const accountInfo = await conn.getAccountInfo(mailerStatePda);
|
|
925
|
+
if (!accountInfo || !accountInfo.data) {
|
|
926
|
+
throw new Error('Mailer not initialized');
|
|
927
|
+
}
|
|
928
|
+
// Parse the state data
|
|
929
|
+
const data = accountInfo.data;
|
|
930
|
+
const ownerClaimable = data.readBigUInt64LE(57); // After discriminator(8) + owner(32) + paused(1) + sendFee(8) + delegationFee(8)
|
|
931
|
+
return Number(ownerClaimable);
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Get delegation for an address
|
|
935
|
+
*/
|
|
936
|
+
async getDelegation(address, chainInfo, connection) {
|
|
937
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
938
|
+
const { programId } = this.getProgramAddresses(chainInfo);
|
|
939
|
+
const addressPubkey = typeof address === 'string' ? new web3_js_1.PublicKey(address) : address;
|
|
940
|
+
const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), addressPubkey.toBuffer()], programId);
|
|
941
|
+
const accountInfo = await conn.getAccountInfo(delegatorInfo);
|
|
942
|
+
if (!accountInfo || !accountInfo.data) {
|
|
943
|
+
return null;
|
|
944
|
+
}
|
|
945
|
+
// Parse the delegatingAddress info data
|
|
946
|
+
const data = accountInfo.data;
|
|
947
|
+
const hasDelegate = data.readUInt8(8) === 1; // After discriminator
|
|
948
|
+
if (!hasDelegate) {
|
|
949
|
+
return null;
|
|
950
|
+
}
|
|
951
|
+
// Read delegate pubkey
|
|
952
|
+
const delegateBytes = data.slice(9, 41); // 32 bytes for pubkey
|
|
953
|
+
return new web3_js_1.PublicKey(delegateBytes);
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Get custom fee percentage for an account
|
|
957
|
+
*/
|
|
958
|
+
async getCustomFeePercentage(account, chainInfo, connection) {
|
|
959
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
960
|
+
const { programId } = this.getProgramAddresses(chainInfo);
|
|
961
|
+
const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
|
|
962
|
+
const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
|
|
963
|
+
const accountInfo = await conn.getAccountInfo(customFeeInfo);
|
|
964
|
+
if (!accountInfo || !accountInfo.data) {
|
|
965
|
+
return 100; // Default to 100% if no custom fee set
|
|
966
|
+
}
|
|
967
|
+
// Parse the custom fee data
|
|
968
|
+
const data = accountInfo.data;
|
|
969
|
+
const percentage = data.readUInt8(8); // After discriminator
|
|
970
|
+
return percentage;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Check if the program is paused
|
|
974
|
+
*/
|
|
975
|
+
async isPaused(chainInfo, connection) {
|
|
976
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
977
|
+
const { mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
978
|
+
const accountInfo = await conn.getAccountInfo(mailerStatePda);
|
|
979
|
+
if (!accountInfo || !accountInfo.data) {
|
|
980
|
+
throw new Error('Mailer not initialized');
|
|
981
|
+
}
|
|
982
|
+
// Parse the state data
|
|
983
|
+
const data = accountInfo.data;
|
|
984
|
+
const paused = data.readUInt8(40); // After discriminator(8) + owner(32)
|
|
985
|
+
return paused === 1;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Get the contract owner
|
|
989
|
+
*/
|
|
990
|
+
async getOwner(chainInfo, connection) {
|
|
991
|
+
const conn = await this.getOrCreateConnection(chainInfo, connection);
|
|
992
|
+
const { mailerStatePda } = this.getProgramAddresses(chainInfo);
|
|
993
|
+
const accountInfo = await conn.getAccountInfo(mailerStatePda);
|
|
994
|
+
if (!accountInfo || !accountInfo.data) {
|
|
995
|
+
throw new Error('Mailer not initialized');
|
|
996
|
+
}
|
|
997
|
+
// Parse the state data
|
|
998
|
+
const data = accountInfo.data;
|
|
999
|
+
const ownerBytes = data.slice(8, 40); // After discriminator(8)
|
|
1000
|
+
return new web3_js_1.PublicKey(ownerBytes);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
exports.SolanaMailerClient = SolanaMailerClient;
|
|
1004
|
+
//# sourceMappingURL=solana-mailer-client.js.map
|