@solana/offchain-messages 0.0.0 → 5.1.0-canary-20251203224929
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/LICENSE +20 -0
- package/README.md +14 -0
- package/dist/index.browser.cjs +828 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +788 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.native.mjs +788 -0
- package/dist/index.native.mjs.map +1 -0
- package/dist/index.node.cjs +828 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.mjs +788 -0
- package/dist/index.node.mjs.map +1 -0
- package/dist/types/application-domain.d.ts +93 -0
- package/dist/types/application-domain.d.ts.map +1 -0
- package/dist/types/codecs/application-domain.d.ts +54 -0
- package/dist/types/codecs/application-domain.d.ts.map +1 -0
- package/dist/types/codecs/content.d.ts +6 -0
- package/dist/types/codecs/content.d.ts.map +1 -0
- package/dist/types/codecs/envelope.d.ts +31 -0
- package/dist/types/codecs/envelope.d.ts.map +1 -0
- package/dist/types/codecs/message-v0.d.ts +33 -0
- package/dist/types/codecs/message-v0.d.ts.map +1 -0
- package/dist/types/codecs/message-v1.d.ts +33 -0
- package/dist/types/codecs/message-v1.d.ts.map +1 -0
- package/dist/types/codecs/message.d.ts +43 -0
- package/dist/types/codecs/message.d.ts.map +1 -0
- package/dist/types/codecs/preamble-common.d.ts +12 -0
- package/dist/types/codecs/preamble-common.d.ts.map +1 -0
- package/dist/types/codecs/preamble-v0.d.ts +6 -0
- package/dist/types/codecs/preamble-v0.d.ts.map +1 -0
- package/dist/types/codecs/preamble-v1.d.ts +6 -0
- package/dist/types/codecs/preamble-v1.d.ts.map +1 -0
- package/dist/types/codecs/signatures.d.ts +4 -0
- package/dist/types/codecs/signatures.d.ts.map +1 -0
- package/dist/types/codecs/signing-domain.d.ts +5 -0
- package/dist/types/codecs/signing-domain.d.ts.map +1 -0
- package/dist/types/content.d.ts +234 -0
- package/dist/types/content.d.ts.map +1 -0
- package/dist/types/envelope-common.d.ts +9 -0
- package/dist/types/envelope-common.d.ts.map +1 -0
- package/dist/types/envelope-v0.d.ts +11 -0
- package/dist/types/envelope-v0.d.ts.map +1 -0
- package/dist/types/envelope-v1.d.ts +11 -0
- package/dist/types/envelope-v1.d.ts.map +1 -0
- package/dist/types/envelope.d.ts +29 -0
- package/dist/types/envelope.d.ts.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/message-v0.d.ts +75 -0
- package/dist/types/message-v0.d.ts.map +1 -0
- package/dist/types/message-v1.d.ts +7 -0
- package/dist/types/message-v1.d.ts.map +1 -0
- package/dist/types/message.d.ts +7 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/preamble-v0.d.ts +10 -0
- package/dist/types/preamble-v0.d.ts.map +1 -0
- package/dist/types/preamble-v1.d.ts +5 -0
- package/dist/types/preamble-v1.d.ts.map +1 -0
- package/dist/types/signatures.d.ts +138 -0
- package/dist/types/signatures.d.ts.map +1 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/types/version.d.ts.map +1 -0
- package/package.json +85 -7
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
import { isAddress, assertIsAddress, getAddressEncoder, getAddressDecoder, address, getAddressFromPublicKey, getPublicKeyFromAddress } from '@solana/addresses';
|
|
2
|
+
import { isSolanaError, SOLANA_ERROR__ADDRESSES__STRING_LENGTH_OUT_OF_RANGE, SolanaError, SOLANA_ERROR__OFFCHAIN_MESSAGE__APPLICATION_DOMAIN_STRING_LENGTH_OUT_OF_RANGE, SOLANA_ERROR__ADDRESSES__INVALID_BYTE_LENGTH, SOLANA_ERROR__OFFCHAIN_MESSAGE__INVALID_APPLICATION_DOMAIN_BYTE_LENGTH, SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_ENVELOPE_SIGNATURES_CANNOT_BE_ZERO, SOLANA_ERROR__OFFCHAIN_MESSAGE__ENVELOPE_SIGNERS_MISMATCH, SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_SIGNATURES_MISMATCH, SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO, SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_FORMAT_MISMATCH, SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY, SOLANA_ERROR__OFFCHAIN_MESSAGE__RESTRICTED_ASCII_BODY_CHARACTER_OUT_OF_RANGE, SOLANA_ERROR__OFFCHAIN_MESSAGE__MAXIMUM_LENGTH_EXCEEDED, SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_LENGTH_MISMATCH, SOLANA_ERROR__INVARIANT_VIOLATION__SWITCH_MUST_BE_EXHAUSTIVE, SOLANA_ERROR__OFFCHAIN_MESSAGE__VERSION_NUMBER_NOT_SUPPORTED, SOLANA_ERROR__OFFCHAIN_MESSAGE__ADDRESSES_CANNOT_SIGN_OFFCHAIN_MESSAGE, SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATURES_MISSING, SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATURE_VERIFICATION_FAILURE, SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATORIES_MUST_BE_SORTED, SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATORIES_MUST_BE_UNIQUE, SOLANA_ERROR__OFFCHAIN_MESSAGE__UNEXPECTED_VERSION } from '@solana/errors';
|
|
3
|
+
import { transformEncoder, combineCodec, transformDecoder, fixDecoderSize, createDecoder, createEncoder, bytesEqual, fixEncoderSize, offsetDecoder } from '@solana/codecs-core';
|
|
4
|
+
import { getStructEncoder, getBytesEncoder, getStructDecoder, getArrayDecoder, getBytesDecoder, getTupleDecoder, getTupleEncoder, getHiddenPrefixDecoder, getArrayEncoder, getConstantDecoder, getEnumDecoder, getEnumEncoder, getHiddenPrefixEncoder, getConstantEncoder } from '@solana/codecs-data-structures';
|
|
5
|
+
import { getU8Decoder, getU8Encoder, getU16Decoder, getU16Encoder } from '@solana/codecs-numbers';
|
|
6
|
+
import { getUtf8Encoder, getUtf8Decoder } from '@solana/codecs-strings';
|
|
7
|
+
import { signBytes, verifySignature } from '@solana/keys';
|
|
8
|
+
|
|
9
|
+
// src/application-domain.ts
|
|
10
|
+
function isOffchainMessageApplicationDomain(putativeApplicationDomain) {
|
|
11
|
+
return isAddress(putativeApplicationDomain);
|
|
12
|
+
}
|
|
13
|
+
function assertIsOffchainMessageApplicationDomain(putativeApplicationDomain) {
|
|
14
|
+
try {
|
|
15
|
+
assertIsAddress(putativeApplicationDomain);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (isSolanaError(error, SOLANA_ERROR__ADDRESSES__STRING_LENGTH_OUT_OF_RANGE)) {
|
|
18
|
+
throw new SolanaError(
|
|
19
|
+
SOLANA_ERROR__OFFCHAIN_MESSAGE__APPLICATION_DOMAIN_STRING_LENGTH_OUT_OF_RANGE,
|
|
20
|
+
error.context
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
if (isSolanaError(error, SOLANA_ERROR__ADDRESSES__INVALID_BYTE_LENGTH)) {
|
|
24
|
+
throw new SolanaError(
|
|
25
|
+
SOLANA_ERROR__OFFCHAIN_MESSAGE__INVALID_APPLICATION_DOMAIN_BYTE_LENGTH,
|
|
26
|
+
error.context
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function offchainMessageApplicationDomain(putativeApplicationDomain) {
|
|
33
|
+
assertIsOffchainMessageApplicationDomain(putativeApplicationDomain);
|
|
34
|
+
return putativeApplicationDomain;
|
|
35
|
+
}
|
|
36
|
+
function getOffchainMessageApplicationDomainEncoder() {
|
|
37
|
+
return transformEncoder(
|
|
38
|
+
getAddressEncoder(),
|
|
39
|
+
(putativeApplicationDomain) => offchainMessageApplicationDomain(putativeApplicationDomain)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function getOffchainMessageApplicationDomainDecoder() {
|
|
43
|
+
return getAddressDecoder();
|
|
44
|
+
}
|
|
45
|
+
function getOffchainMessageApplicationDomainCodec() {
|
|
46
|
+
return combineCodec(getOffchainMessageApplicationDomainEncoder(), getOffchainMessageApplicationDomainDecoder());
|
|
47
|
+
}
|
|
48
|
+
var OFFCHAIN_MESSAGE_SIGNING_DOMAIN_BYTES = new Uint8Array([
|
|
49
|
+
255,
|
|
50
|
+
115,
|
|
51
|
+
111,
|
|
52
|
+
108,
|
|
53
|
+
97,
|
|
54
|
+
110,
|
|
55
|
+
97,
|
|
56
|
+
32,
|
|
57
|
+
111,
|
|
58
|
+
102,
|
|
59
|
+
102,
|
|
60
|
+
99,
|
|
61
|
+
104,
|
|
62
|
+
97,
|
|
63
|
+
105,
|
|
64
|
+
110
|
|
65
|
+
]);
|
|
66
|
+
function getOffchainMessageSigningDomainDecoder() {
|
|
67
|
+
return getConstantDecoder(OFFCHAIN_MESSAGE_SIGNING_DOMAIN_BYTES);
|
|
68
|
+
}
|
|
69
|
+
function getOffchainMessageSigningDomainEncoder() {
|
|
70
|
+
return getConstantEncoder(OFFCHAIN_MESSAGE_SIGNING_DOMAIN_BYTES);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/codecs/preamble-common.ts
|
|
74
|
+
function getSigningDomainPrefixedDecoder(...fields) {
|
|
75
|
+
return getHiddenPrefixDecoder(getStructDecoder(fields), [getOffchainMessageSigningDomainDecoder()]);
|
|
76
|
+
}
|
|
77
|
+
function getSigningDomainPrefixedEncoder(...fields) {
|
|
78
|
+
return getHiddenPrefixEncoder(getStructEncoder(fields), [getOffchainMessageSigningDomainEncoder()]);
|
|
79
|
+
}
|
|
80
|
+
function getVersionTransformer(fixedVersion) {
|
|
81
|
+
return (version) => {
|
|
82
|
+
if (version > 1) {
|
|
83
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__VERSION_NUMBER_NOT_SUPPORTED, {
|
|
84
|
+
unsupportedVersion: version
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (fixedVersion != null && version !== fixedVersion) {
|
|
88
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__UNEXPECTED_VERSION, {
|
|
89
|
+
actualVersion: version,
|
|
90
|
+
expectedVersion: fixedVersion
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return version;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function createOffchainMessagePreambleDecoder(version, ...fields) {
|
|
97
|
+
return getSigningDomainPrefixedDecoder(
|
|
98
|
+
["version", transformDecoder(getU8Decoder(), getVersionTransformer(version))],
|
|
99
|
+
...fields
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function createOffchainMessagePreambleEncoder(version, ...fields) {
|
|
103
|
+
return getSigningDomainPrefixedEncoder(
|
|
104
|
+
["version", transformEncoder(getU8Encoder(), getVersionTransformer(version))],
|
|
105
|
+
...fields
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function decodeRequiredSignatoryAddresses(bytes) {
|
|
109
|
+
const { version, bytesAfterVersion } = getSigningDomainPrefixedDecoder(
|
|
110
|
+
["version", transformDecoder(getU8Decoder(), getVersionTransformer())],
|
|
111
|
+
["bytesAfterVersion", getBytesDecoder()]
|
|
112
|
+
).decode(bytes);
|
|
113
|
+
return offsetDecoder(
|
|
114
|
+
transformDecoder(getArrayDecoder(getAddressDecoder(), { size: getU8Decoder() }), (signatoryAddresses) => {
|
|
115
|
+
if (signatoryAddresses.length === 0) {
|
|
116
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
117
|
+
}
|
|
118
|
+
return signatoryAddresses;
|
|
119
|
+
}),
|
|
120
|
+
{
|
|
121
|
+
preOffset: ({ preOffset }) => preOffset + (version === 0 ? 32 + 1 : 0)
|
|
122
|
+
}
|
|
123
|
+
).decode(bytesAfterVersion);
|
|
124
|
+
}
|
|
125
|
+
function getSignatoriesComparator() {
|
|
126
|
+
return (x, y) => {
|
|
127
|
+
if (x.length !== y.length) {
|
|
128
|
+
return x.length < y.length ? -1 : 1;
|
|
129
|
+
}
|
|
130
|
+
for (let ii = 0; ii < x.length; ii++) {
|
|
131
|
+
if (x[ii] === y[ii]) {
|
|
132
|
+
continue;
|
|
133
|
+
} else {
|
|
134
|
+
return x[ii] < y[ii] ? -1 : 1;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return 0;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function getSignaturesToEncode(signaturesMap) {
|
|
141
|
+
const signatures = Object.values(signaturesMap);
|
|
142
|
+
if (signatures.length === 0) {
|
|
143
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_ENVELOPE_SIGNATURES_CANNOT_BE_ZERO);
|
|
144
|
+
}
|
|
145
|
+
return signatures.map((signature) => {
|
|
146
|
+
if (!signature) {
|
|
147
|
+
return new Uint8Array(64).fill(0);
|
|
148
|
+
}
|
|
149
|
+
return signature;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function getSignaturesEncoder() {
|
|
153
|
+
return transformEncoder(
|
|
154
|
+
getArrayEncoder(fixEncoderSize(getBytesEncoder(), 64), { size: getU8Encoder() }),
|
|
155
|
+
getSignaturesToEncode
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/codecs/envelope.ts
|
|
160
|
+
function getOffchainMessageEnvelopeEncoder() {
|
|
161
|
+
return transformEncoder(
|
|
162
|
+
getStructEncoder([
|
|
163
|
+
["signatures", getSignaturesEncoder()],
|
|
164
|
+
["content", getBytesEncoder()]
|
|
165
|
+
]),
|
|
166
|
+
(envelope) => {
|
|
167
|
+
const signaturesMapAddresses = Object.keys(envelope.signatures).map(address);
|
|
168
|
+
if (signaturesMapAddresses.length === 0) {
|
|
169
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_ENVELOPE_SIGNATURES_CANNOT_BE_ZERO);
|
|
170
|
+
}
|
|
171
|
+
const signatoryAddresses = decodeAndValidateRequiredSignatoryAddresses(envelope.content);
|
|
172
|
+
const missingRequiredSigners = [];
|
|
173
|
+
const unexpectedSigners = [];
|
|
174
|
+
for (const address2 of signatoryAddresses) {
|
|
175
|
+
if (!signaturesMapAddresses.includes(address2)) {
|
|
176
|
+
missingRequiredSigners.push(address2);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
for (const address2 of signaturesMapAddresses) {
|
|
180
|
+
if (!signatoryAddresses.includes(address2)) {
|
|
181
|
+
unexpectedSigners.push(address2);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (missingRequiredSigners.length || unexpectedSigners.length) {
|
|
185
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__ENVELOPE_SIGNERS_MISMATCH, {
|
|
186
|
+
missingRequiredSigners,
|
|
187
|
+
unexpectedSigners
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const orderedSignatureMap = {};
|
|
191
|
+
for (const address2 of signatoryAddresses) {
|
|
192
|
+
orderedSignatureMap[address2] = envelope.signatures[address2];
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
...envelope,
|
|
196
|
+
signatures: orderedSignatureMap
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
function getOffchainMessageEnvelopeDecoder() {
|
|
202
|
+
return transformDecoder(
|
|
203
|
+
getStructDecoder([
|
|
204
|
+
["signatures", getArrayDecoder(fixDecoderSize(getBytesDecoder(), 64), { size: getU8Decoder() })],
|
|
205
|
+
["content", getBytesDecoder()]
|
|
206
|
+
]),
|
|
207
|
+
decodePartiallyDecodedOffchainMessageEnvelope
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
function getOffchainMessageEnvelopeCodec() {
|
|
211
|
+
return combineCodec(getOffchainMessageEnvelopeEncoder(), getOffchainMessageEnvelopeDecoder());
|
|
212
|
+
}
|
|
213
|
+
function decodePartiallyDecodedOffchainMessageEnvelope(offchainMessageEnvelope) {
|
|
214
|
+
const { content, signatures } = offchainMessageEnvelope;
|
|
215
|
+
if (signatures.length === 0) {
|
|
216
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_ENVELOPE_SIGNATURES_CANNOT_BE_ZERO);
|
|
217
|
+
}
|
|
218
|
+
const signatoryAddresses = decodeAndValidateRequiredSignatoryAddresses(content);
|
|
219
|
+
if (signatoryAddresses.length !== signatures.length) {
|
|
220
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_SIGNATURES_MISMATCH, {
|
|
221
|
+
numRequiredSignatures: signatoryAddresses.length,
|
|
222
|
+
signatoryAddresses,
|
|
223
|
+
signaturesLength: signatures.length
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const signaturesMap = {};
|
|
227
|
+
signatoryAddresses.forEach((address2, index) => {
|
|
228
|
+
const signatureForAddress = signatures[index];
|
|
229
|
+
if (signatureForAddress.every((b) => b === 0)) {
|
|
230
|
+
signaturesMap[address2] = null;
|
|
231
|
+
} else {
|
|
232
|
+
signaturesMap[address2] = signatureForAddress;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return Object.freeze({
|
|
236
|
+
content,
|
|
237
|
+
signatures: Object.freeze(signaturesMap)
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function decodeAndValidateRequiredSignatoryAddresses(bytes) {
|
|
241
|
+
const signatoryAddresses = decodeRequiredSignatoryAddresses(bytes);
|
|
242
|
+
if (signatoryAddresses.length === 0) {
|
|
243
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
244
|
+
}
|
|
245
|
+
return signatoryAddresses;
|
|
246
|
+
}
|
|
247
|
+
var MAX_BODY_BYTES = (
|
|
248
|
+
// Largest 16-bit unsigned integer
|
|
249
|
+
65535
|
|
250
|
+
);
|
|
251
|
+
var MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE = (
|
|
252
|
+
// Space remaining in the mininum IPv6 MTU after network header overhead
|
|
253
|
+
1232
|
|
254
|
+
);
|
|
255
|
+
var OffchainMessageContentFormat = /* @__PURE__ */ ((OffchainMessageContentFormat3) => {
|
|
256
|
+
OffchainMessageContentFormat3[OffchainMessageContentFormat3["RESTRICTED_ASCII_1232_BYTES_MAX"] = 0] = "RESTRICTED_ASCII_1232_BYTES_MAX";
|
|
257
|
+
OffchainMessageContentFormat3[OffchainMessageContentFormat3["UTF8_1232_BYTES_MAX"] = 1] = "UTF8_1232_BYTES_MAX";
|
|
258
|
+
OffchainMessageContentFormat3[OffchainMessageContentFormat3["UTF8_65535_BYTES_MAX"] = 2] = "UTF8_65535_BYTES_MAX";
|
|
259
|
+
return OffchainMessageContentFormat3;
|
|
260
|
+
})(OffchainMessageContentFormat || {});
|
|
261
|
+
function assertIsOffchainMessageContentRestrictedAsciiOf1232BytesMax(putativeContent) {
|
|
262
|
+
if (putativeContent.format !== 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */) {
|
|
263
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_FORMAT_MISMATCH, {
|
|
264
|
+
actualMessageFormat: putativeContent.format,
|
|
265
|
+
expectedMessageFormat: 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (putativeContent.text.length === 0) {
|
|
269
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY);
|
|
270
|
+
}
|
|
271
|
+
if (isTextRestrictedAscii(putativeContent.text) === false) {
|
|
272
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__RESTRICTED_ASCII_BODY_CHARACTER_OUT_OF_RANGE);
|
|
273
|
+
}
|
|
274
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
275
|
+
if (length > MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE) {
|
|
276
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MAXIMUM_LENGTH_EXCEEDED, {
|
|
277
|
+
actualBytes: length,
|
|
278
|
+
maxBytes: MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function isOffchainMessageContentRestrictedAsciiOf1232BytesMax(putativeContent) {
|
|
283
|
+
if (putativeContent.format !== 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */ || putativeContent.text.length === 0 || isTextRestrictedAscii(putativeContent.text) === false) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
287
|
+
return length <= MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE;
|
|
288
|
+
}
|
|
289
|
+
function offchainMessageContentRestrictedAsciiOf1232BytesMax(text) {
|
|
290
|
+
const putativeContent = Object.freeze({
|
|
291
|
+
format: 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */,
|
|
292
|
+
text
|
|
293
|
+
});
|
|
294
|
+
assertIsOffchainMessageContentRestrictedAsciiOf1232BytesMax(putativeContent);
|
|
295
|
+
return putativeContent;
|
|
296
|
+
}
|
|
297
|
+
function assertIsOffchainMessageContentUtf8Of1232BytesMax(putativeContent) {
|
|
298
|
+
if (putativeContent.text.length === 0) {
|
|
299
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY);
|
|
300
|
+
}
|
|
301
|
+
if (putativeContent.format !== 1 /* UTF8_1232_BYTES_MAX */) {
|
|
302
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_FORMAT_MISMATCH, {
|
|
303
|
+
actualMessageFormat: putativeContent.format,
|
|
304
|
+
expectedMessageFormat: 1 /* UTF8_1232_BYTES_MAX */
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
308
|
+
if (length > MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE) {
|
|
309
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MAXIMUM_LENGTH_EXCEEDED, {
|
|
310
|
+
actualBytes: length,
|
|
311
|
+
maxBytes: MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function isOffchainMessageContentUtf8Of1232BytesMax(putativeContent) {
|
|
316
|
+
if (putativeContent.format !== 1 /* UTF8_1232_BYTES_MAX */ || putativeContent.text.length === 0) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
320
|
+
return length <= MAX_BODY_BYTES_HARDWARE_WALLET_SIGNABLE;
|
|
321
|
+
}
|
|
322
|
+
function offchainMessageContentUtf8Of1232BytesMax(text) {
|
|
323
|
+
const putativeContent = Object.freeze({
|
|
324
|
+
format: 1 /* UTF8_1232_BYTES_MAX */,
|
|
325
|
+
text
|
|
326
|
+
});
|
|
327
|
+
assertIsOffchainMessageContentUtf8Of1232BytesMax(putativeContent);
|
|
328
|
+
return putativeContent;
|
|
329
|
+
}
|
|
330
|
+
function assertIsOffchainMessageContentUtf8Of65535BytesMax(putativeContent) {
|
|
331
|
+
if (putativeContent.format !== 2 /* UTF8_65535_BYTES_MAX */) {
|
|
332
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_FORMAT_MISMATCH, {
|
|
333
|
+
actualMessageFormat: putativeContent.format,
|
|
334
|
+
expectedMessageFormat: 2 /* UTF8_65535_BYTES_MAX */
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
if (putativeContent.text.length === 0) {
|
|
338
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY);
|
|
339
|
+
}
|
|
340
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
341
|
+
if (length > MAX_BODY_BYTES) {
|
|
342
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MAXIMUM_LENGTH_EXCEEDED, {
|
|
343
|
+
actualBytes: length,
|
|
344
|
+
maxBytes: MAX_BODY_BYTES
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function isOffchainMessageContentUtf8Of65535BytesMax(putativeContent) {
|
|
349
|
+
if (putativeContent.format !== 2 /* UTF8_65535_BYTES_MAX */ || putativeContent.text.length === 0) {
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
const length = getUtf8Encoder().getSizeFromValue(putativeContent.text);
|
|
353
|
+
return length <= MAX_BODY_BYTES;
|
|
354
|
+
}
|
|
355
|
+
function offchainMessageContentUtf8Of65535BytesMax(text) {
|
|
356
|
+
const putativeContent = Object.freeze({
|
|
357
|
+
format: 2 /* UTF8_65535_BYTES_MAX */,
|
|
358
|
+
text
|
|
359
|
+
});
|
|
360
|
+
assertIsOffchainMessageContentUtf8Of65535BytesMax(putativeContent);
|
|
361
|
+
return putativeContent;
|
|
362
|
+
}
|
|
363
|
+
function isTextRestrictedAscii(putativeRestrictedAsciiString) {
|
|
364
|
+
return /^[\x20-\x7e]+$/.test(putativeRestrictedAsciiString);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// src/message-v0.ts
|
|
368
|
+
function assertIsOffchainMessageRestrictedAsciiOf1232BytesMax(putativeMessage) {
|
|
369
|
+
assertIsOffchainMessageContentRestrictedAsciiOf1232BytesMax(putativeMessage.content);
|
|
370
|
+
}
|
|
371
|
+
function assertIsOffchainMessageUtf8Of1232BytesMax(putativeMessage) {
|
|
372
|
+
assertIsOffchainMessageContentUtf8Of1232BytesMax(putativeMessage.content);
|
|
373
|
+
}
|
|
374
|
+
function assertIsOffchainMessageUtf8Of65535BytesMax(putativeMessage) {
|
|
375
|
+
assertIsOffchainMessageContentUtf8Of65535BytesMax(putativeMessage.content);
|
|
376
|
+
}
|
|
377
|
+
function getOffchainMessageContentFormatDecoder() {
|
|
378
|
+
return getEnumDecoder(OffchainMessageContentFormat, {
|
|
379
|
+
useValuesAsDiscriminators: true
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function getOffchainMessageContentFormatEncoder() {
|
|
383
|
+
return getEnumEncoder(OffchainMessageContentFormat, {
|
|
384
|
+
useValuesAsDiscriminators: true
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/codecs/preamble-v0.ts
|
|
389
|
+
function getOffchainMessageV0PreambleDecoder() {
|
|
390
|
+
return createOffchainMessagePreambleDecoder(
|
|
391
|
+
/* version */
|
|
392
|
+
0,
|
|
393
|
+
["applicationDomain", getOffchainMessageApplicationDomainDecoder()],
|
|
394
|
+
["messageFormat", getOffchainMessageContentFormatDecoder()],
|
|
395
|
+
[
|
|
396
|
+
"requiredSignatories",
|
|
397
|
+
transformDecoder(getArrayDecoder(getAddressDecoder(), { size: getU8Decoder() }), (signatoryAddresses) => {
|
|
398
|
+
if (signatoryAddresses.length === 0) {
|
|
399
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
400
|
+
}
|
|
401
|
+
return signatoryAddresses.map((address2) => Object.freeze({ address: address2 }));
|
|
402
|
+
})
|
|
403
|
+
],
|
|
404
|
+
["messageLength", getU16Decoder()]
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
function getOffchainMessageV0PreambleEncoder() {
|
|
408
|
+
return createOffchainMessagePreambleEncoder(
|
|
409
|
+
/* version */
|
|
410
|
+
0,
|
|
411
|
+
["applicationDomain", getOffchainMessageApplicationDomainEncoder()],
|
|
412
|
+
["messageFormat", getOffchainMessageContentFormatEncoder()],
|
|
413
|
+
[
|
|
414
|
+
"requiredSignatories",
|
|
415
|
+
transformEncoder(
|
|
416
|
+
getArrayEncoder(getAddressEncoder(), { size: getU8Encoder() }),
|
|
417
|
+
(signatoryAddresses) => {
|
|
418
|
+
if (signatoryAddresses.length === 0) {
|
|
419
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
420
|
+
}
|
|
421
|
+
return signatoryAddresses.map(({ address: address2 }) => address2);
|
|
422
|
+
}
|
|
423
|
+
)
|
|
424
|
+
],
|
|
425
|
+
["messageLength", getU16Encoder()]
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/codecs/message-v0.ts
|
|
430
|
+
function getOffchainMessageV0Decoder() {
|
|
431
|
+
return transformDecoder(
|
|
432
|
+
getTupleDecoder([getOffchainMessageV0PreambleDecoder(), getUtf8Decoder()]),
|
|
433
|
+
([{ messageLength, messageFormat, requiredSignatories, ...preambleRest }, text]) => {
|
|
434
|
+
const actualLength = getUtf8Encoder().getSizeFromValue(text);
|
|
435
|
+
if (messageLength !== actualLength) {
|
|
436
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_LENGTH_MISMATCH, {
|
|
437
|
+
actualLength,
|
|
438
|
+
specifiedLength: messageLength
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
const offchainMessage = Object.freeze({
|
|
442
|
+
...preambleRest,
|
|
443
|
+
content: Object.freeze({
|
|
444
|
+
format: messageFormat,
|
|
445
|
+
text
|
|
446
|
+
}),
|
|
447
|
+
requiredSignatories: Object.freeze(requiredSignatories)
|
|
448
|
+
});
|
|
449
|
+
switch (messageFormat) {
|
|
450
|
+
case 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */: {
|
|
451
|
+
assertIsOffchainMessageRestrictedAsciiOf1232BytesMax(offchainMessage);
|
|
452
|
+
return offchainMessage;
|
|
453
|
+
}
|
|
454
|
+
case 1 /* UTF8_1232_BYTES_MAX */: {
|
|
455
|
+
assertIsOffchainMessageUtf8Of1232BytesMax(offchainMessage);
|
|
456
|
+
return offchainMessage;
|
|
457
|
+
}
|
|
458
|
+
case 2 /* UTF8_65535_BYTES_MAX */: {
|
|
459
|
+
assertIsOffchainMessageUtf8Of65535BytesMax(offchainMessage);
|
|
460
|
+
return offchainMessage;
|
|
461
|
+
}
|
|
462
|
+
default: {
|
|
463
|
+
throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__SWITCH_MUST_BE_EXHAUSTIVE, {
|
|
464
|
+
unexpectedValue: messageFormat
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
function getOffchainMessageV0Encoder() {
|
|
472
|
+
return transformEncoder(
|
|
473
|
+
getTupleEncoder([getOffchainMessageV0PreambleEncoder(), getUtf8Encoder()]),
|
|
474
|
+
(offchainMessage) => {
|
|
475
|
+
const { content, ...preamble } = offchainMessage;
|
|
476
|
+
switch (offchainMessage.content.format) {
|
|
477
|
+
case 0 /* RESTRICTED_ASCII_1232_BYTES_MAX */: {
|
|
478
|
+
assertIsOffchainMessageRestrictedAsciiOf1232BytesMax(offchainMessage);
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
case 1 /* UTF8_1232_BYTES_MAX */: {
|
|
482
|
+
assertIsOffchainMessageUtf8Of1232BytesMax(offchainMessage);
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
case 2 /* UTF8_65535_BYTES_MAX */: {
|
|
486
|
+
assertIsOffchainMessageUtf8Of65535BytesMax(offchainMessage);
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
default: {
|
|
490
|
+
throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__SWITCH_MUST_BE_EXHAUSTIVE, {
|
|
491
|
+
unexpectedValue: offchainMessage.content
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const messageLength = getUtf8Encoder().getSizeFromValue(content.text);
|
|
496
|
+
const compiledPreamble = {
|
|
497
|
+
...preamble,
|
|
498
|
+
messageFormat: content.format,
|
|
499
|
+
messageLength
|
|
500
|
+
};
|
|
501
|
+
return [compiledPreamble, content.text];
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
function getOffchainMessageV0Codec() {
|
|
506
|
+
return combineCodec(getOffchainMessageV0Encoder(), getOffchainMessageV0Decoder());
|
|
507
|
+
}
|
|
508
|
+
function getOffchainMessageV1PreambleDecoder() {
|
|
509
|
+
return createOffchainMessagePreambleDecoder(
|
|
510
|
+
/* version */
|
|
511
|
+
1,
|
|
512
|
+
[
|
|
513
|
+
"requiredSignatories",
|
|
514
|
+
transformDecoder(
|
|
515
|
+
getArrayDecoder(fixDecoderSize(getBytesDecoder(), 32), { size: getU8Decoder() }),
|
|
516
|
+
(signatoryAddressesBytes) => {
|
|
517
|
+
if (signatoryAddressesBytes.length === 0) {
|
|
518
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
519
|
+
}
|
|
520
|
+
const comparator = getSignatoriesComparator();
|
|
521
|
+
for (let ii = 0; ii < signatoryAddressesBytes.length - 1; ii++) {
|
|
522
|
+
switch (comparator(signatoryAddressesBytes[ii], signatoryAddressesBytes[ii + 1])) {
|
|
523
|
+
case 0:
|
|
524
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATORIES_MUST_BE_UNIQUE);
|
|
525
|
+
case 1:
|
|
526
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATORIES_MUST_BE_SORTED);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const addressDecoder = getAddressDecoder();
|
|
530
|
+
return signatoryAddressesBytes.map(
|
|
531
|
+
(addressBytes) => Object.freeze({
|
|
532
|
+
address: addressDecoder.decode(addressBytes)
|
|
533
|
+
})
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
)
|
|
537
|
+
]
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
function getOffchainMessageV1PreambleEncoder() {
|
|
541
|
+
return createOffchainMessagePreambleEncoder(
|
|
542
|
+
/* version */
|
|
543
|
+
1,
|
|
544
|
+
[
|
|
545
|
+
"requiredSignatories",
|
|
546
|
+
transformEncoder(
|
|
547
|
+
transformEncoder(
|
|
548
|
+
getArrayEncoder(getBytesEncoder(), { size: getU8Encoder() }),
|
|
549
|
+
(signatoryAddressesBytes) => {
|
|
550
|
+
return signatoryAddressesBytes.toSorted(getSignatoriesComparator());
|
|
551
|
+
}
|
|
552
|
+
),
|
|
553
|
+
(signatoryAddresses) => {
|
|
554
|
+
if (signatoryAddresses.length === 0) {
|
|
555
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__NUM_REQUIRED_SIGNERS_CANNOT_BE_ZERO);
|
|
556
|
+
}
|
|
557
|
+
const seenSignatories = /* @__PURE__ */ new Set();
|
|
558
|
+
for (const { address: address2 } of signatoryAddresses) {
|
|
559
|
+
if (seenSignatories.has(address2)) {
|
|
560
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATORIES_MUST_BE_UNIQUE);
|
|
561
|
+
}
|
|
562
|
+
seenSignatories.add(address2);
|
|
563
|
+
}
|
|
564
|
+
const addressEncoder = getAddressEncoder();
|
|
565
|
+
return signatoryAddresses.map(({ address: address2 }) => addressEncoder.encode(address2));
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
]
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/codecs/message-v1.ts
|
|
573
|
+
function getOffchainMessageV1Decoder() {
|
|
574
|
+
return transformDecoder(
|
|
575
|
+
getTupleDecoder([getOffchainMessageV1PreambleDecoder(), getUtf8Decoder()]),
|
|
576
|
+
([{ requiredSignatories, ...preambleRest }, text]) => {
|
|
577
|
+
if (text.length === 0) {
|
|
578
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY);
|
|
579
|
+
}
|
|
580
|
+
return Object.freeze({
|
|
581
|
+
...preambleRest,
|
|
582
|
+
content: text,
|
|
583
|
+
requiredSignatories: Object.freeze(requiredSignatories)
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
function getOffchainMessageV1Encoder() {
|
|
589
|
+
return transformEncoder(
|
|
590
|
+
getTupleEncoder([getOffchainMessageV1PreambleEncoder(), getUtf8Encoder()]),
|
|
591
|
+
(offchainMessage) => {
|
|
592
|
+
const { content, ...compiledPreamble } = offchainMessage;
|
|
593
|
+
if (content.length === 0) {
|
|
594
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__MESSAGE_MUST_BE_NON_EMPTY);
|
|
595
|
+
}
|
|
596
|
+
return [compiledPreamble, content];
|
|
597
|
+
}
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
function getOffchainMessageV1Codec() {
|
|
601
|
+
return combineCodec(getOffchainMessageV1Encoder(), getOffchainMessageV1Decoder());
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/codecs/message.ts
|
|
605
|
+
function getOffchainMessageDecoder() {
|
|
606
|
+
return createDecoder({
|
|
607
|
+
read(bytes, offset) {
|
|
608
|
+
const version = getHiddenPrefixDecoder(getU8Decoder(), [
|
|
609
|
+
// Discard the signing domain
|
|
610
|
+
getOffchainMessageSigningDomainDecoder()
|
|
611
|
+
]).decode(bytes, offset);
|
|
612
|
+
switch (version) {
|
|
613
|
+
case 0:
|
|
614
|
+
return getOffchainMessageV0Decoder().read(bytes, offset);
|
|
615
|
+
case 1:
|
|
616
|
+
return getOffchainMessageV1Decoder().read(bytes, offset);
|
|
617
|
+
default:
|
|
618
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__VERSION_NUMBER_NOT_SUPPORTED, {
|
|
619
|
+
unsupportedVersion: version
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
function getOffchainMessageEncoder() {
|
|
626
|
+
return createEncoder({
|
|
627
|
+
getSizeFromValue: (offchainMessage) => {
|
|
628
|
+
const { version } = offchainMessage;
|
|
629
|
+
switch (version) {
|
|
630
|
+
case 0:
|
|
631
|
+
return getOffchainMessageV0Encoder().getSizeFromValue(offchainMessage);
|
|
632
|
+
case 1:
|
|
633
|
+
return getOffchainMessageV1Encoder().getSizeFromValue(offchainMessage);
|
|
634
|
+
default:
|
|
635
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__VERSION_NUMBER_NOT_SUPPORTED, {
|
|
636
|
+
unsupportedVersion: version
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
write: (offchainMessage, bytes, offset) => {
|
|
641
|
+
const { version } = offchainMessage;
|
|
642
|
+
switch (version) {
|
|
643
|
+
case 0:
|
|
644
|
+
return getOffchainMessageV0Encoder().write(offchainMessage, bytes, offset);
|
|
645
|
+
case 1:
|
|
646
|
+
return getOffchainMessageV1Encoder().write(offchainMessage, bytes, offset);
|
|
647
|
+
default:
|
|
648
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__VERSION_NUMBER_NOT_SUPPORTED, {
|
|
649
|
+
unsupportedVersion: version
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
function getOffchainMessageCodec() {
|
|
656
|
+
return combineCodec(getOffchainMessageEncoder(), getOffchainMessageDecoder());
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// src/envelope-common.ts
|
|
660
|
+
function compileOffchainMessageEnvelopeUsingEncoder(offchainMessage, encoder) {
|
|
661
|
+
const offchainMessageBytes = encoder.encode(offchainMessage);
|
|
662
|
+
const signatures = {};
|
|
663
|
+
for (const { address: address2 } of offchainMessage.requiredSignatories) {
|
|
664
|
+
signatures[address2] = null;
|
|
665
|
+
}
|
|
666
|
+
return Object.freeze({
|
|
667
|
+
content: offchainMessageBytes,
|
|
668
|
+
signatures: Object.freeze(signatures)
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/envelope-v0.ts
|
|
673
|
+
function compileOffchainMessageV0Envelope(offchainMessage) {
|
|
674
|
+
return compileOffchainMessageEnvelopeUsingEncoder(offchainMessage, getOffchainMessageV0Encoder());
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/envelope-v1.ts
|
|
678
|
+
function compileOffchainMessageV1Envelope(offchainMessage) {
|
|
679
|
+
return compileOffchainMessageEnvelopeUsingEncoder(offchainMessage, getOffchainMessageV1Encoder());
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/envelope.ts
|
|
683
|
+
function compileOffchainMessageEnvelope(offchainMessage) {
|
|
684
|
+
const { version } = offchainMessage;
|
|
685
|
+
switch (version) {
|
|
686
|
+
case 0:
|
|
687
|
+
return compileOffchainMessageV0Envelope(offchainMessage);
|
|
688
|
+
case 1:
|
|
689
|
+
return compileOffchainMessageV1Envelope(offchainMessage);
|
|
690
|
+
default:
|
|
691
|
+
throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__SWITCH_MUST_BE_EXHAUSTIVE, {
|
|
692
|
+
unexpectedValue: version
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async function partiallySignOffchainMessageEnvelope(keyPairs, offchainMessageEnvelope) {
|
|
697
|
+
let newSignatures;
|
|
698
|
+
let unexpectedSigners;
|
|
699
|
+
const requiredSignatoryAddresses = decodeRequiredSignatoryAddresses(offchainMessageEnvelope.content);
|
|
700
|
+
await Promise.all(
|
|
701
|
+
keyPairs.map(async (keyPair) => {
|
|
702
|
+
const address2 = await getAddressFromPublicKey(keyPair.publicKey);
|
|
703
|
+
if (!requiredSignatoryAddresses.includes(address2)) {
|
|
704
|
+
unexpectedSigners ||= /* @__PURE__ */ new Set();
|
|
705
|
+
unexpectedSigners.add(address2);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
if (unexpectedSigners) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
const existingSignature = offchainMessageEnvelope.signatures[address2];
|
|
712
|
+
const newSignature = await signBytes(keyPair.privateKey, offchainMessageEnvelope.content);
|
|
713
|
+
if (existingSignature != null && bytesEqual(newSignature, existingSignature)) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
newSignatures ||= {};
|
|
717
|
+
newSignatures[address2] = newSignature;
|
|
718
|
+
})
|
|
719
|
+
);
|
|
720
|
+
if (unexpectedSigners && unexpectedSigners.size > 0) {
|
|
721
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__ADDRESSES_CANNOT_SIGN_OFFCHAIN_MESSAGE, {
|
|
722
|
+
expectedAddresses: requiredSignatoryAddresses,
|
|
723
|
+
unexpectedAddresses: [...unexpectedSigners]
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
if (!newSignatures) {
|
|
727
|
+
return offchainMessageEnvelope;
|
|
728
|
+
}
|
|
729
|
+
return Object.freeze({
|
|
730
|
+
...offchainMessageEnvelope,
|
|
731
|
+
signatures: Object.freeze({
|
|
732
|
+
...offchainMessageEnvelope.signatures,
|
|
733
|
+
...newSignatures
|
|
734
|
+
})
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
async function signOffchainMessageEnvelope(keyPairs, offchainMessageEnvelope) {
|
|
738
|
+
const out = await partiallySignOffchainMessageEnvelope(keyPairs, offchainMessageEnvelope);
|
|
739
|
+
assertIsFullySignedOffchainMessageEnvelope(out);
|
|
740
|
+
Object.freeze(out);
|
|
741
|
+
return out;
|
|
742
|
+
}
|
|
743
|
+
function isFullySignedOffchainMessageEnvelope(offchainMessage) {
|
|
744
|
+
return Object.entries(offchainMessage.signatures).every(([_, signatureBytes]) => !!signatureBytes);
|
|
745
|
+
}
|
|
746
|
+
function assertIsFullySignedOffchainMessageEnvelope(offchainMessage) {
|
|
747
|
+
const missingSigs = [];
|
|
748
|
+
Object.entries(offchainMessage.signatures).forEach(([address2, signatureBytes]) => {
|
|
749
|
+
if (!signatureBytes) {
|
|
750
|
+
missingSigs.push(address2);
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
if (missingSigs.length > 0) {
|
|
754
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATURES_MISSING, {
|
|
755
|
+
addresses: missingSigs
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
async function verifyOffchainMessageEnvelope(offchainMessageEnvelope) {
|
|
760
|
+
let errorContext;
|
|
761
|
+
const requiredSignatories = decodeRequiredSignatoryAddresses(offchainMessageEnvelope.content);
|
|
762
|
+
await Promise.all(
|
|
763
|
+
requiredSignatories.map(async (address2) => {
|
|
764
|
+
const signature = offchainMessageEnvelope.signatures[address2];
|
|
765
|
+
if (signature == null) {
|
|
766
|
+
errorContext ||= {};
|
|
767
|
+
errorContext.signatoriesWithMissingSignatures ||= [];
|
|
768
|
+
errorContext.signatoriesWithMissingSignatures.push(address2);
|
|
769
|
+
} else {
|
|
770
|
+
const publicKey = await getPublicKeyFromAddress(address2);
|
|
771
|
+
if (await verifySignature(publicKey, signature, offchainMessageEnvelope.content)) {
|
|
772
|
+
return true;
|
|
773
|
+
} else {
|
|
774
|
+
errorContext ||= {};
|
|
775
|
+
errorContext.signatoriesWithInvalidSignatures ||= [];
|
|
776
|
+
errorContext.signatoriesWithInvalidSignatures.push(address2);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
})
|
|
780
|
+
);
|
|
781
|
+
if (errorContext) {
|
|
782
|
+
throw new SolanaError(SOLANA_ERROR__OFFCHAIN_MESSAGE__SIGNATURE_VERIFICATION_FAILURE, errorContext);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
export { OffchainMessageContentFormat, assertIsFullySignedOffchainMessageEnvelope, assertIsOffchainMessageApplicationDomain, assertIsOffchainMessageContentRestrictedAsciiOf1232BytesMax, assertIsOffchainMessageContentUtf8Of1232BytesMax, assertIsOffchainMessageContentUtf8Of65535BytesMax, assertIsOffchainMessageRestrictedAsciiOf1232BytesMax, assertIsOffchainMessageUtf8Of1232BytesMax, assertIsOffchainMessageUtf8Of65535BytesMax, compileOffchainMessageEnvelope, compileOffchainMessageV0Envelope, compileOffchainMessageV1Envelope, getOffchainMessageApplicationDomainCodec, getOffchainMessageApplicationDomainDecoder, getOffchainMessageApplicationDomainEncoder, getOffchainMessageCodec, getOffchainMessageDecoder, getOffchainMessageEncoder, getOffchainMessageEnvelopeCodec, getOffchainMessageEnvelopeDecoder, getOffchainMessageEnvelopeEncoder, getOffchainMessageV0Codec, getOffchainMessageV0Decoder, getOffchainMessageV0Encoder, getOffchainMessageV1Codec, getOffchainMessageV1Decoder, getOffchainMessageV1Encoder, isFullySignedOffchainMessageEnvelope, isOffchainMessageApplicationDomain, isOffchainMessageContentRestrictedAsciiOf1232BytesMax, isOffchainMessageContentUtf8Of1232BytesMax, isOffchainMessageContentUtf8Of65535BytesMax, offchainMessageApplicationDomain, offchainMessageContentRestrictedAsciiOf1232BytesMax, offchainMessageContentUtf8Of1232BytesMax, offchainMessageContentUtf8Of65535BytesMax, partiallySignOffchainMessageEnvelope, signOffchainMessageEnvelope, verifyOffchainMessageEnvelope };
|
|
787
|
+
//# sourceMappingURL=index.native.mjs.map
|
|
788
|
+
//# sourceMappingURL=index.native.mjs.map
|