@rhinestone/sdk 0.0.0-dev-20260917224650 → 0.0.0-dev-20260921165705

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.
Files changed (75) hide show
  1. package/README.md +11 -26
  2. package/dist/src/actions/runtime.d.ts.map +1 -1
  3. package/dist/src/api/account.d.ts +62 -91
  4. package/dist/src/api/account.d.ts.map +1 -1
  5. package/dist/src/api/account.js +47 -736
  6. package/dist/src/api/accounts.d.ts +1 -1
  7. package/dist/src/api/accounts.d.ts.map +1 -1
  8. package/dist/src/api/accounts.js +3 -121
  9. package/dist/src/api/compose-types.d.ts +0 -9
  10. package/dist/src/api/compose-types.d.ts.map +1 -1
  11. package/dist/src/api/compose.d.ts.map +1 -1
  12. package/dist/src/api/compose.js +5 -50
  13. package/dist/src/api/sdk.d.ts +2 -2
  14. package/dist/src/api/sdk.d.ts.map +1 -1
  15. package/dist/src/api/sdk.js +1 -1
  16. package/dist/src/chains/caip2.d.ts.map +1 -1
  17. package/dist/src/chains/caip2.js +0 -5
  18. package/dist/src/chains/non-evm.d.ts +12 -132
  19. package/dist/src/chains/non-evm.d.ts.map +1 -1
  20. package/dist/src/chains/non-evm.js +1 -30
  21. package/dist/src/clients/orchestrator/auth.d.ts +1 -1
  22. package/dist/src/clients/orchestrator/auth.d.ts.map +1 -1
  23. package/dist/src/clients/orchestrator/auth.js +2 -2
  24. package/dist/src/clients/orchestrator/client.js +6 -6
  25. package/dist/src/clients/orchestrator/errors.d.ts +2 -22
  26. package/dist/src/clients/orchestrator/errors.d.ts.map +1 -1
  27. package/dist/src/clients/orchestrator/errors.js +6 -61
  28. package/dist/src/clients/orchestrator/mappers.d.ts +0 -2
  29. package/dist/src/clients/orchestrator/mappers.d.ts.map +1 -1
  30. package/dist/src/clients/orchestrator/mappers.js +2 -87
  31. package/dist/src/clients/orchestrator/port.d.ts +3 -3
  32. package/dist/src/clients/orchestrator/port.d.ts.map +1 -1
  33. package/dist/src/clients/orchestrator/public.d.ts +7 -55
  34. package/dist/src/clients/orchestrator/public.d.ts.map +1 -1
  35. package/dist/src/clients/orchestrator/types.d.ts +5 -23
  36. package/dist/src/clients/orchestrator/types.d.ts.map +1 -1
  37. package/dist/src/clients/orchestrator/wire.d.ts +19 -1
  38. package/dist/src/clients/orchestrator/wire.d.ts.map +1 -1
  39. package/dist/src/config/account.d.ts +13 -216
  40. package/dist/src/config/account.d.ts.map +1 -1
  41. package/dist/src/errors/execution.d.ts +1 -11
  42. package/dist/src/errors/execution.d.ts.map +1 -1
  43. package/dist/src/errors/execution.js +1 -27
  44. package/dist/src/errors/index.d.ts +3 -4
  45. package/dist/src/errors/index.d.ts.map +1 -1
  46. package/dist/src/errors/index.js +4 -7
  47. package/dist/src/hypercore/market.d.ts +1 -1
  48. package/dist/src/hypercore/market.js +1 -1
  49. package/dist/src/index.d.ts +7 -7
  50. package/dist/src/index.d.ts.map +1 -1
  51. package/dist/src/index.js +2 -2
  52. package/dist/src/transactions/intents/normalize.d.ts.map +1 -1
  53. package/dist/src/transactions/intents/normalize.js +2 -9
  54. package/dist/src/transactions/intents/prepare.d.ts.map +1 -1
  55. package/dist/src/transactions/intents/prepare.js +6 -11
  56. package/dist/src/transactions/intents/submit.d.ts.map +1 -1
  57. package/dist/src/transactions/intents/submit.js +0 -4
  58. package/dist/src/transactions/intents/types.d.ts +3 -61
  59. package/dist/src/transactions/intents/types.d.ts.map +1 -1
  60. package/dist/src/utils/index.d.ts +9 -9
  61. package/dist/src/utils/index.d.ts.map +1 -1
  62. package/dist/src/utils/index.js +6 -6
  63. package/package.json +13 -8
  64. package/dist/src/accounts/solana/address.d.ts +0 -28
  65. package/dist/src/accounts/solana/address.d.ts.map +0 -1
  66. package/dist/src/accounts/solana/address.js +0 -105
  67. package/dist/src/errors/capability.d.ts +0 -23
  68. package/dist/src/errors/capability.d.ts.map +0 -1
  69. package/dist/src/errors/capability.js +0 -41
  70. package/dist/src/transactions/intents/solana-instructions.d.ts +0 -14
  71. package/dist/src/transactions/intents/solana-instructions.d.ts.map +0 -1
  72. package/dist/src/transactions/intents/solana-instructions.js +0 -114
  73. package/dist/src/transactions/intents/solana.d.ts +0 -89
  74. package/dist/src/transactions/intents/solana.d.ts.map +0 -1
  75. package/dist/src/transactions/intents/solana.js +0 -305
@@ -1,45 +1,25 @@
1
- import { isAddress } from 'viem';
2
- import { asSwigNamespace, locateSwig } from '../accounts/solana/address.js';
3
- import { formatCaip2, parseCaip2, toEvmChainReference } from '../chains/caip2.js';
1
+ import { parseCaip2, toEvmChainReference } from '../chains/caip2.js';
4
2
  import { getChainById, getChainReference } from '../chains/catalog.js';
5
- import { solanaAddress, } from '../chains/non-evm.js';
6
3
  import { normalizeTokenAddress, validateTokenAddresses } from '../chains/tokens.js';
7
4
  import { createStaticAccountRuntime } from '../config/account-runtime.js';
8
5
  import { materializeAccountInvocationContext, resolveAccountConfig, } from '../config/resolve.js';
9
- import { AccountVmNotConfiguredError, ManagedSolanaAccountNotSupportedError, UnsupportedAccountCapabilityError, } from '../errors/capability.js';
10
- import { IndependentSigningNotSupportedError, InvalidSolanaTransactionArtifactError, MismatchedOwnerSignaturesError, QuoteNotInPreparedTransactionError, } from '../errors/execution.js';
6
+ import { IndependentSigningNotSupportedError, MismatchedOwnerSignaturesError, QuoteNotInPreparedTransactionError, } from '../errors/execution.js';
11
7
  import { resolveHyperCoreAction } from '../hypercore/resolve.js';
12
8
  import { ecdsaSignerId, webauthnSignerId, } from '../modules/validators/signer-id.js';
13
9
  import { projectIntentAccount, projectIntentRecipient, } from '../transactions/intents/account.js';
14
10
  import { projectCompatibleIntentInput, projectCompatibleQuote, } from '../transactions/intents/compatibility.js';
15
11
  import { normalizeIntentQuote } from '../transactions/intents/normalize.js';
16
- import { solanaChainId, } from '../transactions/intents/solana.js';
17
- import { normalizeSolanaAddressLookupTables, normalizeSolanaInstructions, } from '../transactions/intents/solana-instructions.js';
18
12
  import { adaptSignerSelection, adaptUserOperationSignerSelection, } from './signer-selection.js';
19
- function cloneArtifactValue(value) {
20
- if (Array.isArray(value)) {
21
- return value.map(cloneArtifactValue);
22
- }
23
- if (value && typeof value === 'object') {
24
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [
25
- key,
26
- cloneArtifactValue(item),
27
- ]));
28
- }
29
- return value;
30
- }
31
13
  function toPublicQuote(quote) {
32
14
  const compatible = projectCompatibleQuote(quote);
33
- return cloneArtifactValue({
15
+ return {
34
16
  intentId: compatible.intentId,
35
17
  expiresAt: compatible.expiresAt,
36
18
  estimatedFillTime: compatible.estimatedFillTime,
37
19
  settlementLayer: compatible.settlementLayer,
38
20
  signData: {
39
21
  origin: [...compatible.signData.origin],
40
- ...(compatible.signData.destination
41
- ? { destination: compatible.signData.destination }
42
- : {}),
22
+ destination: compatible.signData.destination,
43
23
  ...(compatible.signData.targetExecution
44
24
  ? { targetExecution: compatible.signData.targetExecution }
45
25
  : {}),
@@ -49,7 +29,7 @@ function toPublicQuote(quote) {
49
29
  ? { tokenRequirements: compatible.tokenRequirements }
50
30
  : {}),
51
31
  ...(compatible.bridgeFill ? { bridgeFill: compatible.bridgeFill } : {}),
52
- });
32
+ };
53
33
  }
54
34
  function toPreparedTransactionData(prepared, transaction, cache) {
55
35
  const data = {
@@ -64,51 +44,6 @@ function toPreparedTransactionData(prepared, transaction, cache) {
64
44
  cache.set(data, prepared);
65
45
  return data;
66
46
  }
67
- function solanaMetadata(input) {
68
- const binding = {
69
- namespace: input.namespace,
70
- endpoint: input.endpoint,
71
- chain: solanaChainId(input.chain),
72
- caip2: input.chain.caip2,
73
- accountAddress: input.accountAddress,
74
- accountType: input.accountType,
75
- authority: input.authority,
76
- swigAddress: input.swigAddress,
77
- walletAddress: input.walletAddress,
78
- };
79
- const action = input.action;
80
- if (action.kind === 'instructions') {
81
- return { kind: 'solana-instructions', ...binding };
82
- }
83
- const delivery = action.delivery;
84
- return delivery.kind === 'cross-chain'
85
- ? {
86
- kind: 'solana-cross-chain',
87
- ...binding,
88
- mint: action.mint,
89
- destinationChain: delivery.chainId,
90
- destinationToken: delivery.token,
91
- recipient: delivery.recipient,
92
- }
93
- : {
94
- kind: 'solana',
95
- ...binding,
96
- mint: action.mint,
97
- recipient: delivery.recipient,
98
- };
99
- }
100
- function toPreparedSolanaTransactionData(prepared, transaction) {
101
- return {
102
- quotes: {
103
- traceId: prepared.traceId,
104
- best: toPublicQuote(prepared.quote),
105
- all: prepared.quotes.map(toPublicQuote),
106
- },
107
- execution: solanaMetadata(prepared.input),
108
- intentInput: projectCompatibleIntentInput(prepared.request),
109
- transaction,
110
- };
111
- }
112
47
  function selectedPublicQuote(prepared, intentId) {
113
48
  if (!intentId)
114
49
  return prepared.quotes.best;
@@ -129,9 +64,8 @@ function reconstructInput(context, prepared, intentId) {
129
64
  : normalizeIntentQuote(candidate)),
130
65
  // The public prepared data only carries the serialized request, so the
131
66
  // reconstructed request holds decimal strings where the internal type
132
- // declares bigints. Sound because submission only re-serializes it (a no-op
133
- // on strings, keeping the sponsorship digest stable) and reads
134
- // `options.sponsorSettings`.
67
+ // declares bigints. Sound because nothing after preparation reads it: the
68
+ // sponsorship digest was taken at quote time.
135
69
  request: prepared.intentInput,
136
70
  intentInput: adaptTransaction(context, prepared.transaction),
137
71
  };
@@ -141,12 +75,8 @@ function toSignedTransactionData(prepared, signed, cache) {
141
75
  ...prepared,
142
76
  quote: toPublicQuote(signed.prepared.quote),
143
77
  originSignatures: signed.originSignatures,
144
- ...(signed.destinationSignature
145
- ? { destinationSignature: signed.destinationSignature }
146
- : {}),
147
- ...(signed.targetSignature
148
- ? { targetExecutionSignature: signed.targetSignature }
149
- : {}),
78
+ destinationSignature: signed.destinationSignature,
79
+ targetExecutionSignature: signed.targetSignature,
150
80
  };
151
81
  cache.set(data, signed);
152
82
  return data;
@@ -156,143 +86,21 @@ function referenceChain() {
156
86
  // needs some EVM chain reference. With no bundled chain set, use mainnet.
157
87
  return toEvmChainReference(1);
158
88
  }
159
- export function createAccountFacade(compatibilityConfig, publicConfig, composition) {
89
+ export function createAccountFacade(compatibilityConfig, composition) {
160
90
  // Intent identity caches are facade-scoped. Values crossing account/SDK
161
91
  // instances are reconstructed and validated by the receiving account.
162
92
  const preparedIntents = new WeakMap();
163
93
  const signedIntents = new WeakMap();
164
94
  const context = (method) => materializeAccountInvocationContext(composition.config, compatibilityConfig, method);
165
95
  const workflowsFor = (ctx) => composition.createAccount(ctx).workflows;
166
- const hasManagedSolana = Boolean(publicConfig.solana && 'owner' in publicConfig.solana);
167
- const capturedSolanaContext = hasManagedSolana
168
- ? context('get-address')
169
- : undefined;
170
- const capturedSolanaIdentity = capturedSolanaContext
171
- ? workflowsFor(capturedSolanaContext).getAddress(capturedSolanaContext, referenceChain())
172
- : undefined;
173
- const capturedSolanaEndpoint = capturedSolanaContext?.sdk.orchestratorUrl;
174
- const capturedSolanaAccountType = capturedSolanaContext
175
- ? capturedSolanaContext.account.account.kind === 'eoa'
176
- ? 'EOA'
177
- : capturedSolanaContext.account.account.kind === 'hca'
178
- ? 'GENERIC'
179
- : 'ERC7579'
180
- : undefined;
181
- const solanaOwner = () => {
182
- const branch = publicConfig.solana;
183
- if (!branch || !('owner' in branch) || !branch.owner) {
184
- throw new UnsupportedAccountCapabilityError('A managed Solana source is not configured on this account.', { vm: 'solana' });
185
- }
186
- return branch.owner.account;
187
- };
188
- const solanaTransfer = (ctx, transaction) => {
189
- assertSupportedTransaction(transaction, publicConfig);
190
- if (ctx.sdk.environment !== 'development' ||
191
- ctx.sdk.orchestratorUrl !== capturedSolanaEndpoint) {
192
- throw new ManagedSolanaAccountNotSupportedError('Managed Solana execution remains bound to the development environment and endpoint captured when the account was created.');
193
- }
194
- if (!isSolanaOrigin(transaction)) {
195
- throw new InvalidSolanaTransactionArtifactError('the transaction is not a Solana-origin transfer');
196
- }
197
- const accountAddress = capturedSolanaIdentity;
198
- if (!accountAddress || !capturedSolanaAccountType) {
199
- throw new UnsupportedAccountCapabilityError('A managed Solana source is not configured on this account.', { vm: 'solana' });
200
- }
201
- const location = locateSwig(asSwigNamespace('dev-v1'), accountAddress);
202
- const common = {
203
- accountAddress,
204
- accountType: capturedSolanaAccountType,
205
- authority: solanaOwner().address,
206
- walletAddress: location.wallet,
207
- swigAddress: location.swig,
208
- namespace: 'dev-v1',
209
- endpoint: ctx.sdk.orchestratorUrl,
210
- ...(transaction.appFees ? { appFees: transaction.appFees } : {}),
211
- ...(transaction.protocolFees
212
- ? { protocolFees: transaction.protocolFees }
213
- : {}),
214
- ...(() => {
215
- const sponsorSettings = toSponsorSettings(transaction.sponsored);
216
- return sponsorSettings ? { sponsorSettings } : {};
217
- })(),
218
- };
219
- if (isCrossChainSolanaOrigin(transaction)) {
220
- return {
221
- ...common,
222
- chain: transaction.sourceChains[0],
223
- action: {
224
- kind: 'transfer',
225
- mint: transaction.sourceTokens[0].address,
226
- ...(transaction.tokenRequests[0].amount === undefined
227
- ? {}
228
- : { amount: transaction.tokenRequests[0].amount }),
229
- delivery: {
230
- kind: 'cross-chain',
231
- chainId: transaction.targetChain.id,
232
- token: transaction.tokenRequests[0].address,
233
- // Resolved here rather than in `normalizeTransaction` so the
234
- // prepare and reconstruct paths agree on the same recipient.
235
- recipient: transaction.recipient ?? accountAddress,
236
- },
237
- },
238
- };
239
- }
240
- if (isSolanaInstructionExecution(transaction)) {
241
- return {
242
- ...common,
243
- chain: transaction.chain,
244
- action: {
245
- kind: 'instructions',
246
- instructions: normalizeSolanaInstructions(transaction.instructions),
247
- ...(transaction.addressLookupTables
248
- ? { addressLookupTables: transaction.addressLookupTables }
249
- : {}),
250
- },
251
- };
252
- }
253
- return {
254
- ...common,
255
- chain: transaction.chain,
256
- action: {
257
- kind: 'transfer',
258
- mint: transaction.tokenRequests[0].address,
259
- ...(transaction.tokenRequests[0].amount === undefined
260
- ? {}
261
- : { amount: transaction.tokenRequests[0].amount }),
262
- delivery: { kind: 'same-chain', recipient: transaction.recipient },
263
- },
264
- };
265
- };
266
- const assertSolanaMetadata = (actual, expected) => {
267
- const expectedEntries = Object.entries(solanaMetadata(expected));
268
- if (!actual ||
269
- Object.keys(actual).length !== expectedEntries.length ||
270
- expectedEntries.some(([key, value]) => actual[key] !== value)) {
271
- throw new InvalidSolanaTransactionArtifactError('the execution binding does not match this account, environment, chain, recipient, or mint');
272
- }
273
- };
274
- const resolveSolanaPrepared = (ctx, prepared, intentId, explicitQuote) => {
275
- const transfer = solanaTransfer(ctx, prepared.transaction);
276
- assertSolanaMetadata(prepared.execution, transfer);
277
- const quote = explicitQuote ?? selectedPublicQuote(prepared, intentId);
278
- return workflowsFor(ctx).reconstructSolanaIntent({
279
- traceId: prepared.quotes.traceId,
280
- transfer,
281
- intentInput: prepared.intentInput,
282
- quote: normalizeIntentQuote(quote),
283
- quotes: prepared.quotes.all.map((candidate) => normalizeIntentQuote(candidate)),
284
- });
285
- };
286
96
  const resolvePrepared = (ctx, prepared, intentId) => {
287
- assertSupportedTransaction(prepared.transaction, publicConfig);
288
- assertSupportedSignData(selectedPublicQuote(prepared, intentId).signData);
289
97
  const cached = preparedIntents.get(prepared);
290
98
  if (cached && !intentId)
291
99
  return Promise.resolve(cached);
292
100
  return workflowsFor(ctx).reconstructPreparedIntent(ctx, reconstructInput(ctx, prepared, intentId));
293
101
  };
294
102
  const account = {
295
- config: publicConfig,
103
+ config: compatibilityConfig,
296
104
  deploy(chain, params) {
297
105
  const ctx = context('deploy');
298
106
  return workflowsFor(ctx).deploy(ctx, toEvmChainReference(chain.id), {
@@ -320,106 +128,49 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
320
128
  },
321
129
  async prepareTransaction(transaction) {
322
130
  const ctx = context('prepare-intent');
323
- const initiallyNormalized = normalizeTransaction(transaction, publicConfig);
324
- const normalized = 'targetChain' in initiallyNormalized &&
325
- initiallyNormalized.targetChain !== undefined &&
326
- 'kind' in initiallyNormalized.targetChain &&
327
- initiallyNormalized.targetChain.kind === 'svm' &&
328
- initiallyNormalized.recipient === undefined &&
329
- capturedSolanaIdentity
330
- ? Object.freeze({
331
- ...initiallyNormalized,
332
- recipient: locateSwig(asSwigNamespace('dev-v1'), capturedSolanaIdentity).wallet,
333
- })
334
- : initiallyNormalized;
335
- if (isSolanaOrigin(normalized)) {
336
- const prepared = await workflowsFor(ctx).prepareSolanaIntent(solanaTransfer(ctx, normalized));
337
- return toPreparedSolanaTransactionData(prepared, normalized);
338
- }
339
131
  // Before the quote, not after: the quote's `signData` registers an agent
340
132
  // derived from the action's bytes, so the action has to be concrete here.
341
133
  const hyperCoreAction = await resolveHyperCoreAction({
342
- options: normalized.hyperCore,
343
- account: workflowsFor(ctx).getAddress(ctx, referenceChain()),
134
+ options: transaction.hyperCore,
135
+ account: account.getAddress(),
344
136
  ...(ctx.sdk.hyperliquid ? { hyperliquid: ctx.sdk.hyperliquid } : {}),
345
137
  });
346
- const automaticSources = 'targetChain' in normalized &&
347
- normalized.targetChain !== undefined &&
348
- normalized.sourceChains === undefined
349
- ? await workflowsFor(ctx).getEligibleEvmSourceChains(destinationChainReference(normalized.targetChain))
350
- : undefined;
351
- if (automaticSources && automaticSources.length === 0) {
352
- throw new UnsupportedAccountCapabilityError('No managed EVM source chains are eligible for this destination.');
353
- }
354
- const prepared = await workflowsFor(ctx).prepareIntent(ctx, adaptTransaction(ctx, normalized, hyperCoreAction, automaticSources?.map(({ id }) => id)));
355
- return toPreparedTransactionData(prepared, normalized, preparedIntents);
138
+ const prepared = await workflowsFor(ctx).prepareIntent(ctx, adaptTransaction(ctx, transaction, hyperCoreAction));
139
+ return toPreparedTransactionData(prepared, transaction, preparedIntents);
356
140
  },
357
141
  getTransactionMessages(preparedTransaction, options) {
358
- assertSupportedTransaction(preparedTransaction.transaction, publicConfig);
359
142
  const quote = selectedPublicQuote(preparedTransaction, options?.intentId);
360
- if (!isSolanaOrigin(preparedTransaction.transaction)) {
361
- assertSupportedSignData(quote.signData);
362
- }
363
- else {
364
- const ctx = context('get-intent-messages');
365
- resolveSolanaPrepared(ctx, preparedTransaction, options?.intentId);
366
- }
367
143
  return {
368
144
  origin: [...quote.signData.origin],
369
- ...(quote.signData.destination
370
- ? { destination: quote.signData.destination }
371
- : {}),
145
+ destination: quote.signData.destination,
372
146
  ...(quote.signData.targetExecution
373
147
  ? { targetExecution: quote.signData.targetExecution }
374
148
  : {}),
375
149
  };
376
150
  },
377
- signTransaction: (async (preparedTransaction, options) => {
151
+ signTransaction: ((preparedTransaction, options) => {
378
152
  const ctx = context('sign-intent');
379
153
  const workflows = workflowsFor(ctx);
380
- if (isSolanaOrigin(preparedTransaction.transaction)) {
381
- if (options && 'owner' in options) {
382
- throw new IndependentSigningNotSupportedError({
383
- context: { vm: 'solana' },
384
- });
385
- }
386
- const prepared = resolveSolanaPrepared(ctx, preparedTransaction, options?.intentId);
387
- const signed = await workflows.signSolanaIntent({
388
- prepared,
389
- owner: solanaOwner(),
390
- });
391
- return {
392
- ...preparedTransaction,
393
- quote: toPublicQuote(signed.prepared.quote),
394
- originSignatures: [signed.signature],
395
- };
396
- }
397
154
  if (options && 'owner' in options) {
398
155
  // Independent owner signing is unsupported for smart-session intents;
399
156
  // reject before resolving sessions (which would issue an RPC read),
400
157
  // matching the legacy fast-fail.
401
158
  if (preparedTransaction.transaction.signers?.type === 'session') {
402
- throw new IndependentSigningNotSupportedError();
159
+ return Promise.reject(new IndependentSigningNotSupportedError());
403
160
  }
404
161
  const signerId = signerIdForOwner(options.owner);
405
- const internal = await resolvePrepared(ctx, preparedTransaction, options.intentId);
406
- return workflows.signIntentAsOwner(ctx, internal, {
162
+ return resolvePrepared(ctx, preparedTransaction, options.intentId).then((internal) => workflows.signIntentAsOwner(ctx, internal, {
407
163
  signerId,
408
164
  ...(options.validatorId === undefined
409
165
  ? {}
410
166
  : { validatorId: options.validatorId }),
411
- });
167
+ }));
412
168
  }
413
- const internal = await resolvePrepared(ctx, preparedTransaction, options?.intentId);
414
- const { intent } = await workflows.signIntent(ctx, internal);
415
- return toSignedTransactionData(preparedTransaction, intent, signedIntents);
169
+ return resolvePrepared(ctx, preparedTransaction, options?.intentId)
170
+ .then((internal) => workflows.signIntent(ctx, internal))
171
+ .then(({ intent }) => toSignedTransactionData(preparedTransaction, intent, signedIntents));
416
172
  }),
417
173
  async assembleTransaction(preparedTransaction, signatures) {
418
- if (isSolanaOrigin(preparedTransaction.transaction)) {
419
- throw new IndependentSigningNotSupportedError({
420
- context: { vm: 'solana' },
421
- });
422
- }
423
174
  const ctx = context('assemble-intent');
424
175
  const workflows = workflowsFor(ctx);
425
176
  const intentIds = [...new Set(signatures.map(({ intentId }) => intentId))];
@@ -431,10 +182,6 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
431
182
  return toSignedTransactionData(preparedTransaction, signed, signedIntents);
432
183
  },
433
184
  async signAuthorizations(preparedTransaction) {
434
- assertSupportedTransaction(preparedTransaction.transaction, publicConfig);
435
- if (isSolanaOrigin(preparedTransaction.transaction)) {
436
- throw new UnsupportedAccountCapabilityError('EIP-7702 authorizations are unavailable for Solana-origin transactions.', { vm: 'solana' });
437
- }
438
185
  const ctx = context('sign-authorizations');
439
186
  const intentInput = adaptTransaction(ctx, preparedTransaction.transaction);
440
187
  const chains = authorizationChains(intentInput);
@@ -469,7 +216,6 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
469
216
  return result.signature;
470
217
  },
471
218
  async signIntent(signData, targetChain, signers) {
472
- assertSupportedSignData(signData);
473
219
  const ctx = context('sign-intent');
474
220
  const result = await workflowsFor(ctx).signIntentFromSignData(ctx, {
475
221
  signData: {
@@ -491,35 +237,8 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
491
237
  };
492
238
  },
493
239
  async submitTransaction(signedTransaction, options) {
494
- assertSupportedTransaction(signedTransaction.transaction, publicConfig);
495
240
  const ctx = context('submit-intent');
496
241
  const workflows = workflowsFor(ctx);
497
- if (isSolanaOrigin(signedTransaction.transaction)) {
498
- if (options && Object.keys(options).length > 0) {
499
- throw new UnsupportedAccountCapabilityError('Solana submission does not accept EVM authorizations or dry-run options.', { vm: 'solana' });
500
- }
501
- if (signedTransaction.originSignatures.length !== 1 ||
502
- typeof signedTransaction.originSignatures[0] !== 'string' ||
503
- signedTransaction.destinationSignature !== undefined ||
504
- signedTransaction.targetExecutionSignature !== undefined) {
505
- throw new InvalidSolanaTransactionArtifactError('submission requires exactly one raw origin signature and no destination or target signature', { intentId: signedTransaction.quote.intentId });
506
- }
507
- const prepared = resolveSolanaPrepared(ctx, signedTransaction, signedTransaction.quote.intentId, signedTransaction.quote);
508
- const submitted = await workflows.submitSolanaIntent({
509
- prepared,
510
- signature: signedTransaction.originSignatures[0],
511
- });
512
- return {
513
- type: 'intent',
514
- id: submitted.intentId,
515
- traceId: submitted.traceId,
516
- ...(submitted.sourceChains
517
- ? { sourceChains: [...submitted.sourceChains] }
518
- : {}),
519
- targetChain: submitted.targetChain,
520
- };
521
- }
522
- assertSupportedSignData(signedTransaction.quote.signData);
523
242
  // Fast path for the same-instance signed object; otherwise (cross-instance
524
243
  // replay or caller-tampered signatures) rebuild from the public shape.
525
244
  const cached = signedIntents.get(signedTransaction);
@@ -641,25 +360,10 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
641
360
  })
642
361
  .then((status) => status.receipt);
643
362
  }),
644
- getAddress: ((vm) => {
645
- if (vm === 'solana') {
646
- if (publicConfig.solana &&
647
- 'address' in publicConfig.solana &&
648
- publicConfig.solana.address) {
649
- return publicConfig.solana.address;
650
- }
651
- if (capturedSolanaIdentity) {
652
- return locateSwig(asSwigNamespace('dev-v1'), capturedSolanaIdentity)
653
- .wallet;
654
- }
655
- throw new AccountVmNotConfiguredError('solana');
656
- }
657
- if (vm !== 'evm' || !publicConfig.evm) {
658
- throw new AccountVmNotConfiguredError(String(vm));
659
- }
363
+ getAddress() {
660
364
  const ctx = context('get-address');
661
365
  return workflowsFor(ctx).getAddress(ctx, referenceChain());
662
- }),
366
+ },
663
367
  getPortfolio(onTestnets = false) {
664
368
  const ctx = context('get-portfolio');
665
369
  return workflowsFor(ctx)
@@ -828,369 +532,6 @@ chainIds) {
828
532
  * authorise. With no session scope there is nothing to narrow against and the
829
533
  * explicit filter stands on its own.
830
534
  */
831
- function assertSupportedSignData(signData) {
832
- const payloads = [
833
- ...signData.origin,
834
- signData.destination,
835
- ...(signData.targetExecution ? [signData.targetExecution] : []),
836
- ];
837
- for (const payload of payloads) {
838
- if (!payload ||
839
- typeof payload !== 'object' ||
840
- (payload.kind !== undefined &&
841
- payload.kind !== 'eip712') ||
842
- typeof payload.primaryType !== 'string' ||
843
- !payload.domain ||
844
- typeof payload.types !== 'object' ||
845
- typeof payload.message !== 'object') {
846
- throw new UnsupportedAccountCapabilityError('Only EIP-712 intent signing data is supported by this account.', { capability: 'intent-signing' });
847
- }
848
- }
849
- }
850
- function isSameChainSolanaOrigin(transaction) {
851
- return ('chain' in transaction &&
852
- typeof transaction.chain === 'object' &&
853
- transaction.chain !== null &&
854
- 'kind' in transaction.chain &&
855
- transaction.chain.kind === 'svm');
856
- }
857
- function isCrossChainSolanaOrigin(transaction) {
858
- const source = transaction
859
- .sourceChains?.[0];
860
- return (typeof source === 'object' &&
861
- source !== null &&
862
- 'kind' in source &&
863
- source.kind === 'svm');
864
- }
865
- function isSolanaInstructionExecution(transaction) {
866
- return (isSameChainSolanaOrigin(transaction) &&
867
- transaction.instructions !== undefined);
868
- }
869
- function isSolanaOrigin(transaction) {
870
- return (isSameChainSolanaOrigin(transaction) ||
871
- isCrossChainSolanaOrigin(transaction));
872
- }
873
- function assertSolanaObjectKeys(value, allowed, label) {
874
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
875
- throw new UnsupportedAccountCapabilityError(`Managed Solana ${label} must be an object.`, { vm: 'solana', field: label });
876
- }
877
- const unsupported = Object.keys(value).find((key) => !allowed.includes(key));
878
- if (unsupported) {
879
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${label}.${unsupported}\`.`, { vm: 'solana', field: `${label}.${unsupported}` });
880
- }
881
- }
882
- function assertSupportedSolanaTransaction(input, config) {
883
- const runsInstructions = input.instructions !== undefined;
884
- const allowed = new Set(runsInstructions
885
- ? ['chain', 'instructions', 'addressLookupTables', 'sponsored']
886
- : [
887
- 'chain',
888
- 'tokenRequests',
889
- 'recipient',
890
- 'sponsored',
891
- 'appFees',
892
- 'protocolFees',
893
- ]);
894
- const unsupported = Object.keys(input).find((key) => !allowed.has(key));
895
- if (unsupported) {
896
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${unsupported}\`.`, { vm: 'solana', field: unsupported });
897
- }
898
- if (!config.solana || !('owner' in config.solana)) {
899
- throw new UnsupportedAccountCapabilityError('A managed Solana source is required for Solana-origin transfers.', { vm: 'solana' });
900
- }
901
- solanaChainId(input.chain);
902
- if (runsInstructions) {
903
- // Shape and limits are enforced by the normalizer, which also produces the
904
- // canonical form `normalizeTransaction` stores.
905
- normalizeSolanaInstructions(input.instructions);
906
- normalizeSolanaAddressLookupTables(input.addressLookupTables);
907
- return;
908
- }
909
- if (!Array.isArray(input.tokenRequests) || input.tokenRequests.length !== 1) {
910
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require exactly one SPL token request.', { vm: 'solana' });
911
- }
912
- const request = input.tokenRequests[0];
913
- assertSolanaObjectKeys(request, ['address', 'amount'], 'tokenRequests[0]');
914
- if (typeof request.address !== 'string') {
915
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require one valid SPL mint address.', { vm: 'solana' });
916
- }
917
- try {
918
- solanaAddress(request.address);
919
- }
920
- catch {
921
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require one valid SPL mint address.', { vm: 'solana' });
922
- }
923
- if (request.amount !== undefined &&
924
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
925
- throw new UnsupportedAccountCapabilityError('A Solana token amount must be a positive bigint when provided.', { vm: 'solana' });
926
- }
927
- if (input.appFees !== undefined) {
928
- assertSolanaObjectKeys(input.appFees, ['feeBps'], 'appFees');
929
- }
930
- if (input.protocolFees !== undefined) {
931
- assertSolanaObjectKeys(input.protocolFees, ['feeBps'], 'protocolFees');
932
- }
933
- if (typeof input.recipient !== 'string') {
934
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require an explicit recipient wallet.', { vm: 'solana' });
935
- }
936
- try {
937
- solanaAddress(input.recipient);
938
- }
939
- catch {
940
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require a valid recipient wallet.', { vm: 'solana' });
941
- }
942
- }
943
- function assertSupportedSolanaOriginDelivery(input, config) {
944
- const allowed = new Set([
945
- 'sourceChains',
946
- 'sourceTokens',
947
- 'targetChain',
948
- 'tokenRequests',
949
- 'recipient',
950
- 'sponsored',
951
- 'appFees',
952
- 'protocolFees',
953
- ]);
954
- const unsupported = Object.keys(input).find((key) => !allowed.has(key));
955
- if (unsupported) {
956
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${unsupported}\`.`, { vm: 'solana', field: unsupported });
957
- }
958
- if (!config.solana || !('owner' in config.solana)) {
959
- throw new UnsupportedAccountCapabilityError('A managed Solana source is required for Solana-origin transfers.', { vm: 'solana' });
960
- }
961
- const sources = input.sourceChains;
962
- if (sources.length !== 1) {
963
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery spends exactly one Solana cluster.', { vm: 'solana', field: 'sourceChains' });
964
- }
965
- solanaChainId(sources[0]);
966
- if (!Array.isArray(input.sourceTokens) || input.sourceTokens.length !== 1) {
967
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires exactly one source SPL mint.', { vm: 'solana', field: 'sourceTokens' });
968
- }
969
- const sourceToken = input.sourceTokens[0];
970
- assertSolanaObjectKeys(sourceToken, ['address'], 'sourceTokens[0]');
971
- try {
972
- solanaAddress(sourceToken.address);
973
- }
974
- catch {
975
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires one valid SPL mint address.', { vm: 'solana', field: 'sourceTokens[0].address' });
976
- }
977
- const target = input.targetChain;
978
- if (!target ||
979
- typeof target !== 'object' ||
980
- 'kind' in target ||
981
- 'caip2' in target ||
982
- typeof target.id !== 'number' ||
983
- !Number.isSafeInteger(target.id) ||
984
- target.id < 0 ||
985
- !formatCaip2(target.id).startsWith('eip155:')) {
986
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires a viem EVM destination chain.', { vm: 'solana', field: 'targetChain' });
987
- }
988
- if (!Array.isArray(input.tokenRequests) || input.tokenRequests.length !== 1) {
989
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires exactly one destination token request.', { vm: 'solana', field: 'tokenRequests' });
990
- }
991
- const request = input.tokenRequests[0];
992
- assertSolanaObjectKeys(request, ['address', 'amount'], 'tokenRequests[0]');
993
- if (typeof request.address !== 'string' || !isAddress(request.address)) {
994
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires an EVM destination token address.', { vm: 'solana', field: 'tokenRequests[0].address' });
995
- }
996
- if (request.amount !== undefined &&
997
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
998
- throw new UnsupportedAccountCapabilityError('A delivery amount must be a positive bigint when provided.', { vm: 'solana', field: 'tokenRequests[0].amount' });
999
- }
1000
- if (input.recipient !== undefined &&
1001
- (typeof input.recipient !== 'string' || !isAddress(input.recipient))) {
1002
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery recipient must be an EVM address.', { vm: 'solana', field: 'recipient' });
1003
- }
1004
- if (input.appFees !== undefined) {
1005
- assertSolanaObjectKeys(input.appFees, ['feeBps'], 'appFees');
1006
- }
1007
- if (input.protocolFees !== undefined) {
1008
- assertSolanaObjectKeys(input.protocolFees, ['feeBps'], 'protocolFees');
1009
- }
1010
- }
1011
- function assertSupportedTransaction(transaction, config) {
1012
- const input = transaction;
1013
- if (isCrossChainSolanaOrigin(transaction)) {
1014
- assertSupportedSolanaOriginDelivery(input, config);
1015
- return;
1016
- }
1017
- const hasChain = Object.hasOwn(input, 'chain') && input.chain !== undefined;
1018
- const hasTarget = Object.hasOwn(input, 'targetChain') && input.targetChain !== undefined;
1019
- if (hasChain === hasTarget) {
1020
- throw new UnsupportedAccountCapabilityError('A transaction must set exactly one of `chain` or `targetChain`.');
1021
- }
1022
- if (hasChain && typeof input.chain === 'object' && input.chain !== null) {
1023
- const chain = input.chain;
1024
- if (chain.kind === 'svm') {
1025
- assertSupportedSolanaTransaction(input, config);
1026
- return;
1027
- }
1028
- }
1029
- if (hasTarget && typeof input.targetChain === 'object' && input.targetChain) {
1030
- const target = input.targetChain;
1031
- if (!('kind' in target || 'caip2' in target) &&
1032
- (typeof target.id !== 'number' ||
1033
- !Number.isSafeInteger(target.id) ||
1034
- target.id < 0 ||
1035
- !formatCaip2(target.id).startsWith('eip155:'))) {
1036
- throw new UnsupportedAccountCapabilityError('A viem EVM destination must use an eip155 chain ID.');
1037
- }
1038
- if (('kind' in target || 'caip2' in target) &&
1039
- !((target.kind === 'svm' &&
1040
- typeof target.caip2 === 'string' &&
1041
- target.caip2.startsWith('solana:')) ||
1042
- (target.kind === 'tvm' &&
1043
- typeof target.caip2 === 'string' &&
1044
- target.caip2.startsWith('tron:')) ||
1045
- (target.kind === 'stellar' &&
1046
- typeof target.caip2 === 'string' &&
1047
- target.caip2.startsWith('stellar:')) ||
1048
- (target.kind === 'hypercore' &&
1049
- (target.caip2 === 'hypercore:spot' ||
1050
- target.caip2 === 'hypercore:perp')))) {
1051
- throw new UnsupportedAccountCapabilityError('The destination chain descriptor has mismatched VM and CAIP-2 fields.');
1052
- }
1053
- if (target.kind === 'svm') {
1054
- if (!Array.isArray(input.tokenRequests) ||
1055
- input.tokenRequests.length === 0) {
1056
- throw new UnsupportedAccountCapabilityError('Solana destinations require at least one token request.', { vm: 'solana' });
1057
- }
1058
- for (const request of input.tokenRequests) {
1059
- if (typeof request.address !== 'string') {
1060
- throw new UnsupportedAccountCapabilityError('Solana token requests require a Solana address.');
1061
- }
1062
- solanaAddress(request.address);
1063
- if (request.amount !== undefined &&
1064
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
1065
- throw new UnsupportedAccountCapabilityError('Solana token request amounts must be positive.');
1066
- }
1067
- }
1068
- // Anything other than a Solana address string would slip past both
1069
- // recipient defaults and then be dropped downstream, quoting a delivery
1070
- // with no receiver at all.
1071
- if (input.recipient !== undefined) {
1072
- if (typeof input.recipient !== 'string') {
1073
- throw new UnsupportedAccountCapabilityError('A Solana delivery recipient must be a Solana address.', { vm: 'solana' });
1074
- }
1075
- solanaAddress(input.recipient);
1076
- }
1077
- if (input.calls !== undefined ||
1078
- input.instructions !== undefined ||
1079
- input.hyperCore !== undefined) {
1080
- throw new UnsupportedAccountCapabilityError('Solana destinations support token delivery only; calls, custom instructions and HyperCore actions are unavailable.', { vm: 'solana' });
1081
- }
1082
- if (input.recipient === undefined && !config.solana) {
1083
- throw new AccountVmNotConfiguredError('solana');
1084
- }
1085
- }
1086
- }
1087
- if (input.sourceChains !== undefined) {
1088
- if (!Array.isArray(input.sourceChains)) {
1089
- throw new UnsupportedAccountCapabilityError('`sourceChains` must be an array of managed source chains.');
1090
- }
1091
- if (input.sourceChains.length === 0) {
1092
- throw new UnsupportedAccountCapabilityError('`sourceChains` must contain at least one managed source.');
1093
- }
1094
- const ids = input.sourceChains.map((value) => typeof value === 'object' && value
1095
- ? value.id
1096
- : null);
1097
- const invalidSource = input.sourceChains.some((value) => {
1098
- if (!value || typeof value !== 'object')
1099
- return true;
1100
- const source = value;
1101
- return (typeof source.id !== 'number' ||
1102
- !Number.isSafeInteger(source.id) ||
1103
- source.id < 0 ||
1104
- Object.hasOwn(source, 'kind') ||
1105
- Object.hasOwn(source, 'caip2') ||
1106
- !formatCaip2(source.id).startsWith('eip155:'));
1107
- });
1108
- if (invalidSource) {
1109
- throw new UnsupportedAccountCapabilityError('Only viem EVM chains from the managed EVM account can be used as sources.');
1110
- }
1111
- if (new Set(ids).size !== ids.length) {
1112
- throw new UnsupportedAccountCapabilityError('`sourceChains` cannot contain duplicate chains.');
1113
- }
1114
- }
1115
- const calls = input.calls;
1116
- if (input.recipient !== undefined) {
1117
- if (Array.isArray(calls) && calls.length > 0) {
1118
- throw new UnsupportedAccountCapabilityError('An explicit delivery recipient cannot execute destination calls. Omit `recipient` to execute with the invoking managed EVM account.');
1119
- }
1120
- if (!Array.isArray(input.tokenRequests) ||
1121
- input.tokenRequests.length === 0) {
1122
- throw new UnsupportedAccountCapabilityError('An explicit delivery recipient requires at least one token request.');
1123
- }
1124
- }
1125
- }
1126
- function freezeSponsorship(sponsored) {
1127
- if (sponsored === undefined || typeof sponsored === 'boolean')
1128
- return {};
1129
- return { sponsored: Object.freeze({ ...sponsored }) };
1130
- }
1131
- export function normalizeTransaction(transaction, config) {
1132
- assertSupportedTransaction(transaction, config);
1133
- if (isCrossChainSolanaOrigin(transaction)) {
1134
- return Object.freeze({
1135
- ...transaction,
1136
- sourceChains: [
1137
- Object.freeze({ ...transaction.sourceChains[0] }),
1138
- ],
1139
- sourceTokens: [
1140
- Object.freeze({ ...transaction.sourceTokens[0] }),
1141
- ],
1142
- tokenRequests: [
1143
- Object.freeze({ ...transaction.tokenRequests[0] }),
1144
- ],
1145
- ...(transaction.appFees
1146
- ? { appFees: Object.freeze({ ...transaction.appFees }) }
1147
- : {}),
1148
- ...(transaction.protocolFees
1149
- ? { protocolFees: Object.freeze({ ...transaction.protocolFees }) }
1150
- : {}),
1151
- ...freezeSponsorship(transaction.sponsored),
1152
- });
1153
- }
1154
- if (isSolanaInstructionExecution(transaction)) {
1155
- const lookupTables = normalizeSolanaAddressLookupTables(transaction.addressLookupTables);
1156
- const { addressLookupTables: _tables, ...rest } = transaction;
1157
- return Object.freeze({
1158
- ...rest,
1159
- chain: Object.freeze({ ...transaction.chain }),
1160
- instructions: normalizeSolanaInstructions(transaction.instructions),
1161
- ...(lookupTables ? { addressLookupTables: lookupTables } : {}),
1162
- ...freezeSponsorship(transaction.sponsored),
1163
- });
1164
- }
1165
- if (isSameChainSolanaOrigin(transaction)) {
1166
- const request = transaction.tokenRequests[0];
1167
- return Object.freeze({
1168
- ...transaction,
1169
- chain: Object.freeze({ ...transaction.chain }),
1170
- tokenRequests: [Object.freeze({ ...request })],
1171
- ...(transaction.appFees
1172
- ? { appFees: Object.freeze({ ...transaction.appFees }) }
1173
- : {}),
1174
- ...(transaction.protocolFees
1175
- ? { protocolFees: Object.freeze({ ...transaction.protocolFees }) }
1176
- : {}),
1177
- ...freezeSponsorship(transaction.sponsored),
1178
- });
1179
- }
1180
- if ('targetChain' in transaction &&
1181
- transaction.targetChain !== undefined &&
1182
- 'kind' in transaction.targetChain &&
1183
- transaction.targetChain.kind === 'svm' &&
1184
- transaction.recipient === undefined &&
1185
- config.solana &&
1186
- 'address' in config.solana) {
1187
- return Object.freeze({
1188
- ...transaction,
1189
- recipient: config.solana.address,
1190
- });
1191
- }
1192
- return Object.freeze({ ...transaction });
1193
- }
1194
535
  function narrowQuoterPin(derived, explicit) {
1195
536
  if (!explicit)
1196
537
  return derived;
@@ -1202,39 +543,7 @@ function narrowQuoterPin(derived, explicit) {
1202
543
  : derived.include.filter((quoter) => !explicit.exclude.includes(quoter));
1203
544
  return { include: narrowed };
1204
545
  }
1205
- /**
1206
- * Translates the public `sponsored` input into the wire's `sponsorSettings`.
1207
- * Shared by both VMs so the two cannot drift.
1208
- */
1209
- function toSponsorSettings(sponsored) {
1210
- if (!sponsored)
1211
- return undefined;
1212
- if (typeof sponsored === 'boolean') {
1213
- return {
1214
- gas: sponsored,
1215
- bridgeFees: sponsored,
1216
- swapFees: sponsored,
1217
- protocolFees: sponsored,
1218
- };
1219
- }
1220
- return {
1221
- gas: sponsored.gas,
1222
- bridgeFees: sponsored.bridging,
1223
- swapFees: sponsored.swaps,
1224
- protocolFees: sponsored.protocolFees ?? false,
1225
- // Omitted rather than sent false when unset: the field rides the
1226
- // server-signature surface, so a key that is present-but-false is not the
1227
- // same bytes as absent.
1228
- ...(sponsored.swapValue ? { swapValue: true } : {}),
1229
- };
1230
- }
1231
- export function adaptTransaction(context, transaction, hyperCoreAction, automaticSourceChainIds) {
1232
- const nonEvmOrigin = 'chain' in transaction && transaction.chain && 'kind' in transaction.chain
1233
- ? transaction.chain.kind
1234
- : transaction.sourceChains?.find((chain) => 'kind' in chain)?.kind;
1235
- if (nonEvmOrigin) {
1236
- throw new UnsupportedAccountCapabilityError('Non-EVM origin execution is not supported yet. Use a viem EVM chain as the managed source.', { vm: nonEvmOrigin });
1237
- }
546
+ export function adaptTransaction(context, transaction, hyperCoreAction) {
1238
547
  const destination = 'chain' in transaction
1239
548
  ? getChainReference(transaction.chain.id)
1240
549
  : 'kind' in transaction.targetChain
@@ -1243,7 +552,7 @@ export function adaptTransaction(context, transaction, hyperCoreAction, automati
1243
552
  const destinationChainId = destination.kind === 'evm' ? destination.id : undefined;
1244
553
  const sourceChains = 'chain' in transaction
1245
554
  ? [getChainReference(transaction.chain.id)]
1246
- : (transaction.sourceChains?.map((chain) => getChainReference(chain.id)) ?? automaticSourceChainIds?.map(getChainReference));
555
+ : transaction.sourceChains?.map((chain) => getChainReference(chain.id));
1247
556
  const evmSources = sourceChains?.flatMap((chain) => chain.kind === 'evm' ? [chain] : []);
1248
557
  return {
1249
558
  destination,
@@ -1279,10 +588,23 @@ export function adaptTransaction(context, transaction, hyperCoreAction, automati
1279
588
  ...('chain' in transaction && transaction.customDeadline !== undefined
1280
589
  ? { customDeadline: transaction.customDeadline }
1281
590
  : {}),
1282
- ...(() => {
1283
- const sponsorSettings = toSponsorSettings(transaction.sponsored);
1284
- return sponsorSettings ? { sponsorSettings } : {};
1285
- })(),
591
+ ...(transaction.sponsored
592
+ ? {
593
+ sponsorSettings: typeof transaction.sponsored === 'boolean'
594
+ ? {
595
+ gas: transaction.sponsored,
596
+ bridgeFees: transaction.sponsored,
597
+ swapFees: transaction.sponsored,
598
+ protocolFees: transaction.sponsored,
599
+ }
600
+ : {
601
+ gas: transaction.sponsored.gas,
602
+ bridgeFees: transaction.sponsored.bridging,
603
+ swapFees: transaction.sponsored.swaps,
604
+ protocolFees: transaction.sponsored.protocolFees ?? false,
605
+ },
606
+ }
607
+ : {}),
1286
608
  ...(transaction.settlementLayers
1287
609
  ? { settlementLayers: transaction.settlementLayers }
1288
610
  : {}),
@@ -1399,12 +721,9 @@ function adaptSessionSelection(transaction, chains) {
1399
721
  ]));
1400
722
  }
1401
723
  const chainIds = new Set(chains.flatMap((chain) => chain.kind === 'evm' && chain.id !== undefined ? [chain.id] : []));
1402
- if ('chain' in transaction && !('kind' in transaction.chain)) {
724
+ if ('chain' in transaction)
1403
725
  chainIds.add(transaction.chain.id);
1404
- }
1405
- if ('targetChain' in transaction &&
1406
- transaction.targetChain &&
1407
- 'id' in transaction.targetChain) {
726
+ if ('targetChain' in transaction && 'id' in transaction.targetChain) {
1408
727
  chainIds.add(transaction.targetChain.id);
1409
728
  }
1410
729
  return Object.fromEntries([...chainIds].map((chainId) => [
@@ -1418,18 +737,11 @@ function adaptSessionSelection(transaction, chains) {
1418
737
  function adaptSourceAssets(sourceAssets, chainIds) {
1419
738
  if (!sourceAssets)
1420
739
  return chainIds ? { chainIds } : undefined;
1421
- const eligible = chainIds ? new Set(chainIds) : undefined;
1422
- const assertEligible = (chainId) => {
1423
- if (eligible && !eligible.has(chainId)) {
1424
- throw new UnsupportedAccountCapabilityError(`Source assets reference chain ${chainId}, which is outside the eligible source scope.`, { chainId });
1425
- }
1426
- };
1427
740
  if (Array.isArray(sourceAssets)) {
1428
741
  if (sourceAssets.length > 0 && typeof sourceAssets[0] === 'object') {
1429
742
  const chainTokens = {};
1430
743
  const chainTokenAmounts = {};
1431
744
  for (const item of sourceAssets) {
1432
- assertEligible(item.chain.id);
1433
745
  const token = normalizeTokenAddress(item.address, item.chain.id, false);
1434
746
  if (item.amount === undefined)
1435
747
  (chainTokens[item.chain.id] ??= []).push(token);
@@ -1452,8 +764,7 @@ function adaptSourceAssets(sourceAssets, chainIds) {
1452
764
  }
1453
765
  // ChainTokenMap: validate every per-chain list too, so symbols can't slip
1454
766
  // through this input the way they can't through tokenRequests / ExactInputConfig.
1455
- for (const [chainId, tokens] of Object.entries(sourceAssets)) {
1456
- assertEligible(Number(chainId));
767
+ for (const tokens of Object.values(sourceAssets)) {
1457
768
  validateTokenAddresses(tokens);
1458
769
  }
1459
770
  return { chainTokens: sourceAssets };