@rhinestone/sdk 0.0.0-dev-20260917215313 → 0.0.0-dev-20260921130703

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 (68) hide show
  1. package/README.md +2 -20
  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 +28 -697
  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/client.js +1 -1
  22. package/dist/src/clients/orchestrator/errors.d.ts +2 -22
  23. package/dist/src/clients/orchestrator/errors.d.ts.map +1 -1
  24. package/dist/src/clients/orchestrator/errors.js +6 -61
  25. package/dist/src/clients/orchestrator/mappers.d.ts +0 -2
  26. package/dist/src/clients/orchestrator/mappers.d.ts.map +1 -1
  27. package/dist/src/clients/orchestrator/mappers.js +2 -87
  28. package/dist/src/clients/orchestrator/public.d.ts +7 -49
  29. package/dist/src/clients/orchestrator/public.d.ts.map +1 -1
  30. package/dist/src/clients/orchestrator/types.d.ts +4 -17
  31. package/dist/src/clients/orchestrator/types.d.ts.map +1 -1
  32. package/dist/src/clients/orchestrator/wire.d.ts +19 -1
  33. package/dist/src/clients/orchestrator/wire.d.ts.map +1 -1
  34. package/dist/src/config/account.d.ts +11 -185
  35. package/dist/src/config/account.d.ts.map +1 -1
  36. package/dist/src/errors/execution.d.ts +1 -11
  37. package/dist/src/errors/execution.d.ts.map +1 -1
  38. package/dist/src/errors/execution.js +1 -27
  39. package/dist/src/errors/index.d.ts +3 -4
  40. package/dist/src/errors/index.d.ts.map +1 -1
  41. package/dist/src/errors/index.js +4 -7
  42. package/dist/src/hypercore/market.d.ts +1 -1
  43. package/dist/src/hypercore/market.js +1 -1
  44. package/dist/src/index.d.ts +7 -7
  45. package/dist/src/index.d.ts.map +1 -1
  46. package/dist/src/index.js +2 -2
  47. package/dist/src/transactions/intents/normalize.d.ts.map +1 -1
  48. package/dist/src/transactions/intents/normalize.js +2 -9
  49. package/dist/src/transactions/intents/prepare.d.ts.map +1 -1
  50. package/dist/src/transactions/intents/prepare.js +1 -10
  51. package/dist/src/transactions/intents/types.d.ts +3 -61
  52. package/dist/src/transactions/intents/types.d.ts.map +1 -1
  53. package/dist/src/utils/index.d.ts +9 -9
  54. package/dist/src/utils/index.d.ts.map +1 -1
  55. package/dist/src/utils/index.js +6 -6
  56. package/package.json +1 -5
  57. package/dist/src/accounts/solana/address.d.ts +0 -28
  58. package/dist/src/accounts/solana/address.d.ts.map +0 -1
  59. package/dist/src/accounts/solana/address.js +0 -105
  60. package/dist/src/errors/capability.d.ts +0 -23
  61. package/dist/src/errors/capability.d.ts.map +0 -1
  62. package/dist/src/errors/capability.js +0 -41
  63. package/dist/src/transactions/intents/solana-instructions.d.ts +0 -14
  64. package/dist/src/transactions/intents/solana-instructions.d.ts.map +0 -1
  65. package/dist/src/transactions/intents/solana-instructions.js +0 -114
  66. package/dist/src/transactions/intents/solana.d.ts +0 -88
  67. package/dist/src/transactions/intents/solana.d.ts.map +0 -1
  68. package/dist/src/transactions/intents/solana.js +0 -302
@@ -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;
@@ -141,12 +76,8 @@ function toSignedTransactionData(prepared, signed, cache) {
141
76
  ...prepared,
142
77
  quote: toPublicQuote(signed.prepared.quote),
143
78
  originSignatures: signed.originSignatures,
144
- ...(signed.destinationSignature
145
- ? { destinationSignature: signed.destinationSignature }
146
- : {}),
147
- ...(signed.targetSignature
148
- ? { targetExecutionSignature: signed.targetSignature }
149
- : {}),
79
+ destinationSignature: signed.destinationSignature,
80
+ targetExecutionSignature: signed.targetSignature,
150
81
  };
151
82
  cache.set(data, signed);
152
83
  return data;
@@ -156,139 +87,21 @@ function referenceChain() {
156
87
  // needs some EVM chain reference. With no bundled chain set, use mainnet.
157
88
  return toEvmChainReference(1);
158
89
  }
159
- export function createAccountFacade(compatibilityConfig, publicConfig, composition) {
90
+ export function createAccountFacade(compatibilityConfig, composition) {
160
91
  // Intent identity caches are facade-scoped. Values crossing account/SDK
161
92
  // instances are reconstructed and validated by the receiving account.
162
93
  const preparedIntents = new WeakMap();
163
94
  const signedIntents = new WeakMap();
164
95
  const context = (method) => materializeAccountInvocationContext(composition.config, compatibilityConfig, method);
165
96
  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
- if (isCrossChainSolanaOrigin(transaction)) {
216
- return {
217
- ...common,
218
- chain: transaction.sourceChains[0],
219
- action: {
220
- kind: 'transfer',
221
- mint: transaction.sourceTokens[0].address,
222
- ...(transaction.tokenRequests[0].amount === undefined
223
- ? {}
224
- : { amount: transaction.tokenRequests[0].amount }),
225
- delivery: {
226
- kind: 'cross-chain',
227
- chainId: transaction.targetChain.id,
228
- token: transaction.tokenRequests[0].address,
229
- // Resolved here rather than in `normalizeTransaction` so the
230
- // prepare and reconstruct paths agree on the same recipient.
231
- recipient: transaction.recipient ?? accountAddress,
232
- },
233
- },
234
- };
235
- }
236
- if (isSolanaInstructionExecution(transaction)) {
237
- return {
238
- ...common,
239
- chain: transaction.chain,
240
- action: {
241
- kind: 'instructions',
242
- instructions: normalizeSolanaInstructions(transaction.instructions),
243
- ...(transaction.addressLookupTables
244
- ? { addressLookupTables: transaction.addressLookupTables }
245
- : {}),
246
- },
247
- };
248
- }
249
- return {
250
- ...common,
251
- chain: transaction.chain,
252
- action: {
253
- kind: 'transfer',
254
- mint: transaction.tokenRequests[0].address,
255
- ...(transaction.tokenRequests[0].amount === undefined
256
- ? {}
257
- : { amount: transaction.tokenRequests[0].amount }),
258
- delivery: { kind: 'same-chain', recipient: transaction.recipient },
259
- },
260
- };
261
- };
262
- const assertSolanaMetadata = (actual, expected) => {
263
- const expectedEntries = Object.entries(solanaMetadata(expected));
264
- if (!actual ||
265
- Object.keys(actual).length !== expectedEntries.length ||
266
- expectedEntries.some(([key, value]) => actual[key] !== value)) {
267
- throw new InvalidSolanaTransactionArtifactError('the execution binding does not match this account, environment, chain, recipient, or mint');
268
- }
269
- };
270
- const resolveSolanaPrepared = (ctx, prepared, intentId, explicitQuote) => {
271
- const transfer = solanaTransfer(ctx, prepared.transaction);
272
- assertSolanaMetadata(prepared.execution, transfer);
273
- const quote = explicitQuote ?? selectedPublicQuote(prepared, intentId);
274
- return workflowsFor(ctx).reconstructSolanaIntent({
275
- traceId: prepared.quotes.traceId,
276
- transfer,
277
- intentInput: prepared.intentInput,
278
- quote: normalizeIntentQuote(quote),
279
- quotes: prepared.quotes.all.map((candidate) => normalizeIntentQuote(candidate)),
280
- });
281
- };
282
97
  const resolvePrepared = (ctx, prepared, intentId) => {
283
- assertSupportedTransaction(prepared.transaction, publicConfig);
284
- assertSupportedSignData(selectedPublicQuote(prepared, intentId).signData);
285
98
  const cached = preparedIntents.get(prepared);
286
99
  if (cached && !intentId)
287
100
  return Promise.resolve(cached);
288
101
  return workflowsFor(ctx).reconstructPreparedIntent(ctx, reconstructInput(ctx, prepared, intentId));
289
102
  };
290
103
  const account = {
291
- config: publicConfig,
104
+ config: compatibilityConfig,
292
105
  deploy(chain, params) {
293
106
  const ctx = context('deploy');
294
107
  return workflowsFor(ctx).deploy(ctx, toEvmChainReference(chain.id), {
@@ -316,106 +129,49 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
316
129
  },
317
130
  async prepareTransaction(transaction) {
318
131
  const ctx = context('prepare-intent');
319
- const initiallyNormalized = normalizeTransaction(transaction, publicConfig);
320
- const normalized = 'targetChain' in initiallyNormalized &&
321
- initiallyNormalized.targetChain !== undefined &&
322
- 'kind' in initiallyNormalized.targetChain &&
323
- initiallyNormalized.targetChain.kind === 'svm' &&
324
- initiallyNormalized.recipient === undefined &&
325
- capturedSolanaIdentity
326
- ? Object.freeze({
327
- ...initiallyNormalized,
328
- recipient: locateSwig(asSwigNamespace('dev-v1'), capturedSolanaIdentity).wallet,
329
- })
330
- : initiallyNormalized;
331
- if (isSolanaOrigin(normalized)) {
332
- const prepared = await workflowsFor(ctx).prepareSolanaIntent(solanaTransfer(ctx, normalized));
333
- return toPreparedSolanaTransactionData(prepared, normalized);
334
- }
335
132
  // Before the quote, not after: the quote's `signData` registers an agent
336
133
  // derived from the action's bytes, so the action has to be concrete here.
337
134
  const hyperCoreAction = await resolveHyperCoreAction({
338
- options: normalized.hyperCore,
339
- account: workflowsFor(ctx).getAddress(ctx, referenceChain()),
135
+ options: transaction.hyperCore,
136
+ account: account.getAddress(),
340
137
  ...(ctx.sdk.hyperliquid ? { hyperliquid: ctx.sdk.hyperliquid } : {}),
341
138
  });
342
- const automaticSources = 'targetChain' in normalized &&
343
- normalized.targetChain !== undefined &&
344
- normalized.sourceChains === undefined
345
- ? await workflowsFor(ctx).getEligibleEvmSourceChains(destinationChainReference(normalized.targetChain))
346
- : undefined;
347
- if (automaticSources && automaticSources.length === 0) {
348
- throw new UnsupportedAccountCapabilityError('No managed EVM source chains are eligible for this destination.');
349
- }
350
- const prepared = await workflowsFor(ctx).prepareIntent(ctx, adaptTransaction(ctx, normalized, hyperCoreAction, automaticSources?.map(({ id }) => id)));
351
- return toPreparedTransactionData(prepared, normalized, preparedIntents);
139
+ const prepared = await workflowsFor(ctx).prepareIntent(ctx, adaptTransaction(ctx, transaction, hyperCoreAction));
140
+ return toPreparedTransactionData(prepared, transaction, preparedIntents);
352
141
  },
353
142
  getTransactionMessages(preparedTransaction, options) {
354
- assertSupportedTransaction(preparedTransaction.transaction, publicConfig);
355
143
  const quote = selectedPublicQuote(preparedTransaction, options?.intentId);
356
- if (!isSolanaOrigin(preparedTransaction.transaction)) {
357
- assertSupportedSignData(quote.signData);
358
- }
359
- else {
360
- const ctx = context('get-intent-messages');
361
- resolveSolanaPrepared(ctx, preparedTransaction, options?.intentId);
362
- }
363
144
  return {
364
145
  origin: [...quote.signData.origin],
365
- ...(quote.signData.destination
366
- ? { destination: quote.signData.destination }
367
- : {}),
146
+ destination: quote.signData.destination,
368
147
  ...(quote.signData.targetExecution
369
148
  ? { targetExecution: quote.signData.targetExecution }
370
149
  : {}),
371
150
  };
372
151
  },
373
- signTransaction: (async (preparedTransaction, options) => {
152
+ signTransaction: ((preparedTransaction, options) => {
374
153
  const ctx = context('sign-intent');
375
154
  const workflows = workflowsFor(ctx);
376
- if (isSolanaOrigin(preparedTransaction.transaction)) {
377
- if (options && 'owner' in options) {
378
- throw new IndependentSigningNotSupportedError({
379
- context: { vm: 'solana' },
380
- });
381
- }
382
- const prepared = resolveSolanaPrepared(ctx, preparedTransaction, options?.intentId);
383
- const signed = await workflows.signSolanaIntent({
384
- prepared,
385
- owner: solanaOwner(),
386
- });
387
- return {
388
- ...preparedTransaction,
389
- quote: toPublicQuote(signed.prepared.quote),
390
- originSignatures: [signed.signature],
391
- };
392
- }
393
155
  if (options && 'owner' in options) {
394
156
  // Independent owner signing is unsupported for smart-session intents;
395
157
  // reject before resolving sessions (which would issue an RPC read),
396
158
  // matching the legacy fast-fail.
397
159
  if (preparedTransaction.transaction.signers?.type === 'session') {
398
- throw new IndependentSigningNotSupportedError();
160
+ return Promise.reject(new IndependentSigningNotSupportedError());
399
161
  }
400
162
  const signerId = signerIdForOwner(options.owner);
401
- const internal = await resolvePrepared(ctx, preparedTransaction, options.intentId);
402
- return workflows.signIntentAsOwner(ctx, internal, {
163
+ return resolvePrepared(ctx, preparedTransaction, options.intentId).then((internal) => workflows.signIntentAsOwner(ctx, internal, {
403
164
  signerId,
404
165
  ...(options.validatorId === undefined
405
166
  ? {}
406
167
  : { validatorId: options.validatorId }),
407
- });
168
+ }));
408
169
  }
409
- const internal = await resolvePrepared(ctx, preparedTransaction, options?.intentId);
410
- const { intent } = await workflows.signIntent(ctx, internal);
411
- return toSignedTransactionData(preparedTransaction, intent, signedIntents);
170
+ return resolvePrepared(ctx, preparedTransaction, options?.intentId)
171
+ .then((internal) => workflows.signIntent(ctx, internal))
172
+ .then(({ intent }) => toSignedTransactionData(preparedTransaction, intent, signedIntents));
412
173
  }),
413
174
  async assembleTransaction(preparedTransaction, signatures) {
414
- if (isSolanaOrigin(preparedTransaction.transaction)) {
415
- throw new IndependentSigningNotSupportedError({
416
- context: { vm: 'solana' },
417
- });
418
- }
419
175
  const ctx = context('assemble-intent');
420
176
  const workflows = workflowsFor(ctx);
421
177
  const intentIds = [...new Set(signatures.map(({ intentId }) => intentId))];
@@ -427,10 +183,6 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
427
183
  return toSignedTransactionData(preparedTransaction, signed, signedIntents);
428
184
  },
429
185
  async signAuthorizations(preparedTransaction) {
430
- assertSupportedTransaction(preparedTransaction.transaction, publicConfig);
431
- if (isSolanaOrigin(preparedTransaction.transaction)) {
432
- throw new UnsupportedAccountCapabilityError('EIP-7702 authorizations are unavailable for Solana-origin transactions.', { vm: 'solana' });
433
- }
434
186
  const ctx = context('sign-authorizations');
435
187
  const intentInput = adaptTransaction(ctx, preparedTransaction.transaction);
436
188
  const chains = authorizationChains(intentInput);
@@ -465,7 +217,6 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
465
217
  return result.signature;
466
218
  },
467
219
  async signIntent(signData, targetChain, signers) {
468
- assertSupportedSignData(signData);
469
220
  const ctx = context('sign-intent');
470
221
  const result = await workflowsFor(ctx).signIntentFromSignData(ctx, {
471
222
  signData: {
@@ -487,35 +238,8 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
487
238
  };
488
239
  },
489
240
  async submitTransaction(signedTransaction, options) {
490
- assertSupportedTransaction(signedTransaction.transaction, publicConfig);
491
241
  const ctx = context('submit-intent');
492
242
  const workflows = workflowsFor(ctx);
493
- if (isSolanaOrigin(signedTransaction.transaction)) {
494
- if (options && Object.keys(options).length > 0) {
495
- throw new UnsupportedAccountCapabilityError('Solana submission does not accept EVM authorizations or dry-run options.', { vm: 'solana' });
496
- }
497
- if (signedTransaction.originSignatures.length !== 1 ||
498
- typeof signedTransaction.originSignatures[0] !== 'string' ||
499
- signedTransaction.destinationSignature !== undefined ||
500
- signedTransaction.targetExecutionSignature !== undefined) {
501
- throw new InvalidSolanaTransactionArtifactError('submission requires exactly one raw origin signature and no destination or target signature', { intentId: signedTransaction.quote.intentId });
502
- }
503
- const prepared = resolveSolanaPrepared(ctx, signedTransaction, signedTransaction.quote.intentId, signedTransaction.quote);
504
- const submitted = await workflows.submitSolanaIntent({
505
- prepared,
506
- signature: signedTransaction.originSignatures[0],
507
- });
508
- return {
509
- type: 'intent',
510
- id: submitted.intentId,
511
- traceId: submitted.traceId,
512
- ...(submitted.sourceChains
513
- ? { sourceChains: [...submitted.sourceChains] }
514
- : {}),
515
- targetChain: submitted.targetChain,
516
- };
517
- }
518
- assertSupportedSignData(signedTransaction.quote.signData);
519
243
  // Fast path for the same-instance signed object; otherwise (cross-instance
520
244
  // replay or caller-tampered signatures) rebuild from the public shape.
521
245
  const cached = signedIntents.get(signedTransaction);
@@ -637,25 +361,10 @@ export function createAccountFacade(compatibilityConfig, publicConfig, compositi
637
361
  })
638
362
  .then((status) => status.receipt);
639
363
  }),
640
- getAddress: ((vm) => {
641
- if (vm === 'solana') {
642
- if (publicConfig.solana &&
643
- 'address' in publicConfig.solana &&
644
- publicConfig.solana.address) {
645
- return publicConfig.solana.address;
646
- }
647
- if (capturedSolanaIdentity) {
648
- return locateSwig(asSwigNamespace('dev-v1'), capturedSolanaIdentity)
649
- .wallet;
650
- }
651
- throw new AccountVmNotConfiguredError('solana');
652
- }
653
- if (vm !== 'evm' || !publicConfig.evm) {
654
- throw new AccountVmNotConfiguredError(String(vm));
655
- }
364
+ getAddress() {
656
365
  const ctx = context('get-address');
657
366
  return workflowsFor(ctx).getAddress(ctx, referenceChain());
658
- }),
367
+ },
659
368
  getPortfolio(onTestnets = false) {
660
369
  const ctx = context('get-portfolio');
661
370
  return workflowsFor(ctx)
@@ -824,367 +533,6 @@ chainIds) {
824
533
  * authorise. With no session scope there is nothing to narrow against and the
825
534
  * explicit filter stands on its own.
826
535
  */
827
- function assertSupportedSignData(signData) {
828
- const payloads = [
829
- ...signData.origin,
830
- signData.destination,
831
- ...(signData.targetExecution ? [signData.targetExecution] : []),
832
- ];
833
- for (const payload of payloads) {
834
- if (!payload ||
835
- typeof payload !== 'object' ||
836
- (payload.kind !== undefined &&
837
- payload.kind !== 'eip712') ||
838
- typeof payload.primaryType !== 'string' ||
839
- !payload.domain ||
840
- typeof payload.types !== 'object' ||
841
- typeof payload.message !== 'object') {
842
- throw new UnsupportedAccountCapabilityError('Only EIP-712 intent signing data is supported by this account.', { capability: 'intent-signing' });
843
- }
844
- }
845
- }
846
- function isSameChainSolanaOrigin(transaction) {
847
- return ('chain' in transaction &&
848
- typeof transaction.chain === 'object' &&
849
- transaction.chain !== null &&
850
- 'kind' in transaction.chain &&
851
- transaction.chain.kind === 'svm');
852
- }
853
- function isCrossChainSolanaOrigin(transaction) {
854
- const source = transaction
855
- .sourceChains?.[0];
856
- return (typeof source === 'object' &&
857
- source !== null &&
858
- 'kind' in source &&
859
- source.kind === 'svm');
860
- }
861
- function isSolanaInstructionExecution(transaction) {
862
- return (isSameChainSolanaOrigin(transaction) &&
863
- transaction.instructions !== undefined);
864
- }
865
- function isSolanaOrigin(transaction) {
866
- return (isSameChainSolanaOrigin(transaction) ||
867
- isCrossChainSolanaOrigin(transaction));
868
- }
869
- function assertSolanaObjectKeys(value, allowed, label) {
870
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
871
- throw new UnsupportedAccountCapabilityError(`Managed Solana ${label} must be an object.`, { vm: 'solana', field: label });
872
- }
873
- const unsupported = Object.keys(value).find((key) => !allowed.includes(key));
874
- if (unsupported) {
875
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${label}.${unsupported}\`.`, { vm: 'solana', field: `${label}.${unsupported}` });
876
- }
877
- }
878
- function assertSupportedSolanaTransaction(input, config) {
879
- const runsInstructions = input.instructions !== undefined;
880
- const allowed = new Set(runsInstructions
881
- ? ['chain', 'instructions', 'addressLookupTables', 'sponsored']
882
- : [
883
- 'chain',
884
- 'tokenRequests',
885
- 'recipient',
886
- 'sponsored',
887
- 'appFees',
888
- 'protocolFees',
889
- ]);
890
- const unsupported = Object.keys(input).find((key) => !allowed.has(key));
891
- if (unsupported) {
892
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${unsupported}\`.`, { vm: 'solana', field: unsupported });
893
- }
894
- if (!config.solana || !('owner' in config.solana)) {
895
- throw new UnsupportedAccountCapabilityError('A managed Solana source is required for Solana-origin transfers.', { vm: 'solana' });
896
- }
897
- solanaChainId(input.chain);
898
- if (input.sponsored !== undefined && input.sponsored !== false) {
899
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers are not sponsorable; omit `sponsored` or set it to false.', { vm: 'solana' });
900
- }
901
- if (runsInstructions) {
902
- // Shape and limits are enforced by the normalizer, which also produces the
903
- // canonical form `normalizeTransaction` stores.
904
- normalizeSolanaInstructions(input.instructions);
905
- normalizeSolanaAddressLookupTables(input.addressLookupTables);
906
- return;
907
- }
908
- if (!Array.isArray(input.tokenRequests) || input.tokenRequests.length !== 1) {
909
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require exactly one SPL token request.', { vm: 'solana' });
910
- }
911
- const request = input.tokenRequests[0];
912
- assertSolanaObjectKeys(request, ['address', 'amount'], 'tokenRequests[0]');
913
- if (typeof request.address !== 'string') {
914
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require one valid SPL mint address.', { vm: 'solana' });
915
- }
916
- try {
917
- solanaAddress(request.address);
918
- }
919
- catch {
920
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require one valid SPL mint address.', { vm: 'solana' });
921
- }
922
- if (request.amount !== undefined &&
923
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
924
- throw new UnsupportedAccountCapabilityError('A Solana token amount must be a positive bigint when provided.', { vm: 'solana' });
925
- }
926
- if (input.appFees !== undefined) {
927
- assertSolanaObjectKeys(input.appFees, ['feeBps'], 'appFees');
928
- }
929
- if (input.protocolFees !== undefined) {
930
- assertSolanaObjectKeys(input.protocolFees, ['feeBps'], 'protocolFees');
931
- }
932
- if (typeof input.recipient !== 'string') {
933
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require an explicit recipient wallet.', { vm: 'solana' });
934
- }
935
- try {
936
- solanaAddress(input.recipient);
937
- }
938
- catch {
939
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers require a valid recipient wallet.', { vm: 'solana' });
940
- }
941
- }
942
- function assertSupportedSolanaOriginDelivery(input, config) {
943
- const allowed = new Set([
944
- 'sourceChains',
945
- 'sourceTokens',
946
- 'targetChain',
947
- 'tokenRequests',
948
- 'recipient',
949
- 'sponsored',
950
- 'appFees',
951
- 'protocolFees',
952
- ]);
953
- const unsupported = Object.keys(input).find((key) => !allowed.has(key));
954
- if (unsupported) {
955
- throw new UnsupportedAccountCapabilityError(`Solana-origin transfers do not support \`${unsupported}\`.`, { vm: 'solana', field: unsupported });
956
- }
957
- if (!config.solana || !('owner' in config.solana)) {
958
- throw new UnsupportedAccountCapabilityError('A managed Solana source is required for Solana-origin transfers.', { vm: 'solana' });
959
- }
960
- const sources = input.sourceChains;
961
- if (sources.length !== 1) {
962
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery spends exactly one Solana cluster.', { vm: 'solana', field: 'sourceChains' });
963
- }
964
- solanaChainId(sources[0]);
965
- if (!Array.isArray(input.sourceTokens) || input.sourceTokens.length !== 1) {
966
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires exactly one source SPL mint.', { vm: 'solana', field: 'sourceTokens' });
967
- }
968
- const sourceToken = input.sourceTokens[0];
969
- assertSolanaObjectKeys(sourceToken, ['address'], 'sourceTokens[0]');
970
- try {
971
- solanaAddress(sourceToken.address);
972
- }
973
- catch {
974
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires one valid SPL mint address.', { vm: 'solana', field: 'sourceTokens[0].address' });
975
- }
976
- const target = input.targetChain;
977
- if (!target ||
978
- typeof target !== 'object' ||
979
- 'kind' in target ||
980
- 'caip2' in target ||
981
- typeof target.id !== 'number' ||
982
- !Number.isSafeInteger(target.id) ||
983
- target.id < 0 ||
984
- !formatCaip2(target.id).startsWith('eip155:')) {
985
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires a viem EVM destination chain.', { vm: 'solana', field: 'targetChain' });
986
- }
987
- if (!Array.isArray(input.tokenRequests) || input.tokenRequests.length !== 1) {
988
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires exactly one destination token request.', { vm: 'solana', field: 'tokenRequests' });
989
- }
990
- const request = input.tokenRequests[0];
991
- assertSolanaObjectKeys(request, ['address', 'amount'], 'tokenRequests[0]');
992
- if (typeof request.address !== 'string' || !isAddress(request.address)) {
993
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery requires an EVM destination token address.', { vm: 'solana', field: 'tokenRequests[0].address' });
994
- }
995
- if (request.amount !== undefined &&
996
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
997
- throw new UnsupportedAccountCapabilityError('A delivery amount must be a positive bigint when provided.', { vm: 'solana', field: 'tokenRequests[0].amount' });
998
- }
999
- if (input.recipient !== undefined &&
1000
- (typeof input.recipient !== 'string' || !isAddress(input.recipient))) {
1001
- throw new UnsupportedAccountCapabilityError('A Solana-origin delivery recipient must be an EVM address.', { vm: 'solana', field: 'recipient' });
1002
- }
1003
- if (input.sponsored !== undefined && input.sponsored !== false) {
1004
- throw new UnsupportedAccountCapabilityError('Managed Solana transfers are not sponsorable; omit `sponsored` or set it to false.', { vm: 'solana' });
1005
- }
1006
- if (input.appFees !== undefined) {
1007
- assertSolanaObjectKeys(input.appFees, ['feeBps'], 'appFees');
1008
- }
1009
- if (input.protocolFees !== undefined) {
1010
- assertSolanaObjectKeys(input.protocolFees, ['feeBps'], 'protocolFees');
1011
- }
1012
- }
1013
- function assertSupportedTransaction(transaction, config) {
1014
- const input = transaction;
1015
- if (isCrossChainSolanaOrigin(transaction)) {
1016
- assertSupportedSolanaOriginDelivery(input, config);
1017
- return;
1018
- }
1019
- const hasChain = Object.hasOwn(input, 'chain') && input.chain !== undefined;
1020
- const hasTarget = Object.hasOwn(input, 'targetChain') && input.targetChain !== undefined;
1021
- if (hasChain === hasTarget) {
1022
- throw new UnsupportedAccountCapabilityError('A transaction must set exactly one of `chain` or `targetChain`.');
1023
- }
1024
- if (hasChain && typeof input.chain === 'object' && input.chain !== null) {
1025
- const chain = input.chain;
1026
- if (chain.kind === 'svm') {
1027
- assertSupportedSolanaTransaction(input, config);
1028
- return;
1029
- }
1030
- }
1031
- if (hasTarget && typeof input.targetChain === 'object' && input.targetChain) {
1032
- const target = input.targetChain;
1033
- if (!('kind' in target || 'caip2' in target) &&
1034
- (typeof target.id !== 'number' ||
1035
- !Number.isSafeInteger(target.id) ||
1036
- target.id < 0 ||
1037
- !formatCaip2(target.id).startsWith('eip155:'))) {
1038
- throw new UnsupportedAccountCapabilityError('A viem EVM destination must use an eip155 chain ID.');
1039
- }
1040
- if (('kind' in target || 'caip2' in target) &&
1041
- !((target.kind === 'svm' &&
1042
- typeof target.caip2 === 'string' &&
1043
- target.caip2.startsWith('solana:')) ||
1044
- (target.kind === 'tvm' &&
1045
- typeof target.caip2 === 'string' &&
1046
- target.caip2.startsWith('tron:')) ||
1047
- (target.kind === 'stellar' &&
1048
- typeof target.caip2 === 'string' &&
1049
- target.caip2.startsWith('stellar:')) ||
1050
- (target.kind === 'hypercore' &&
1051
- (target.caip2 === 'hypercore:spot' ||
1052
- target.caip2 === 'hypercore:perp')))) {
1053
- throw new UnsupportedAccountCapabilityError('The destination chain descriptor has mismatched VM and CAIP-2 fields.');
1054
- }
1055
- if (target.kind === 'svm') {
1056
- if (!Array.isArray(input.tokenRequests) ||
1057
- input.tokenRequests.length === 0) {
1058
- throw new UnsupportedAccountCapabilityError('Solana destinations require at least one token request.', { vm: 'solana' });
1059
- }
1060
- for (const request of input.tokenRequests) {
1061
- if (typeof request.address !== 'string') {
1062
- throw new UnsupportedAccountCapabilityError('Solana token requests require a Solana address.');
1063
- }
1064
- solanaAddress(request.address);
1065
- if (request.amount !== undefined &&
1066
- (typeof request.amount !== 'bigint' || request.amount <= 0n)) {
1067
- throw new UnsupportedAccountCapabilityError('Solana token request amounts must be positive.');
1068
- }
1069
- }
1070
- // Anything other than a Solana address string would slip past both
1071
- // recipient defaults and then be dropped downstream, quoting a delivery
1072
- // with no receiver at all.
1073
- if (input.recipient !== undefined) {
1074
- if (typeof input.recipient !== 'string') {
1075
- throw new UnsupportedAccountCapabilityError('A Solana delivery recipient must be a Solana address.', { vm: 'solana' });
1076
- }
1077
- solanaAddress(input.recipient);
1078
- }
1079
- if (input.calls !== undefined ||
1080
- input.instructions !== undefined ||
1081
- input.hyperCore !== undefined) {
1082
- throw new UnsupportedAccountCapabilityError('Solana destinations support token delivery only; calls, custom instructions and HyperCore actions are unavailable.', { vm: 'solana' });
1083
- }
1084
- if (input.recipient === undefined && !config.solana) {
1085
- throw new AccountVmNotConfiguredError('solana');
1086
- }
1087
- }
1088
- }
1089
- if (input.sourceChains !== undefined) {
1090
- if (!Array.isArray(input.sourceChains)) {
1091
- throw new UnsupportedAccountCapabilityError('`sourceChains` must be an array of managed source chains.');
1092
- }
1093
- if (input.sourceChains.length === 0) {
1094
- throw new UnsupportedAccountCapabilityError('`sourceChains` must contain at least one managed source.');
1095
- }
1096
- const ids = input.sourceChains.map((value) => typeof value === 'object' && value
1097
- ? value.id
1098
- : null);
1099
- const invalidSource = input.sourceChains.some((value) => {
1100
- if (!value || typeof value !== 'object')
1101
- return true;
1102
- const source = value;
1103
- return (typeof source.id !== 'number' ||
1104
- !Number.isSafeInteger(source.id) ||
1105
- source.id < 0 ||
1106
- Object.hasOwn(source, 'kind') ||
1107
- Object.hasOwn(source, 'caip2') ||
1108
- !formatCaip2(source.id).startsWith('eip155:'));
1109
- });
1110
- if (invalidSource) {
1111
- throw new UnsupportedAccountCapabilityError('Only viem EVM chains from the managed EVM account can be used as sources.');
1112
- }
1113
- if (new Set(ids).size !== ids.length) {
1114
- throw new UnsupportedAccountCapabilityError('`sourceChains` cannot contain duplicate chains.');
1115
- }
1116
- }
1117
- const calls = input.calls;
1118
- if (input.recipient !== undefined) {
1119
- if (Array.isArray(calls) && calls.length > 0) {
1120
- throw new UnsupportedAccountCapabilityError('An explicit delivery recipient cannot execute destination calls. Omit `recipient` to execute with the invoking managed EVM account.');
1121
- }
1122
- if (!Array.isArray(input.tokenRequests) ||
1123
- input.tokenRequests.length === 0) {
1124
- throw new UnsupportedAccountCapabilityError('An explicit delivery recipient requires at least one token request.');
1125
- }
1126
- }
1127
- }
1128
- export function normalizeTransaction(transaction, config) {
1129
- assertSupportedTransaction(transaction, config);
1130
- if (isCrossChainSolanaOrigin(transaction)) {
1131
- return Object.freeze({
1132
- ...transaction,
1133
- sourceChains: [
1134
- Object.freeze({ ...transaction.sourceChains[0] }),
1135
- ],
1136
- sourceTokens: [
1137
- Object.freeze({ ...transaction.sourceTokens[0] }),
1138
- ],
1139
- tokenRequests: [
1140
- Object.freeze({ ...transaction.tokenRequests[0] }),
1141
- ],
1142
- ...(transaction.appFees
1143
- ? { appFees: Object.freeze({ ...transaction.appFees }) }
1144
- : {}),
1145
- ...(transaction.protocolFees
1146
- ? { protocolFees: Object.freeze({ ...transaction.protocolFees }) }
1147
- : {}),
1148
- });
1149
- }
1150
- if (isSolanaInstructionExecution(transaction)) {
1151
- const lookupTables = normalizeSolanaAddressLookupTables(transaction.addressLookupTables);
1152
- const { addressLookupTables: _tables, ...rest } = transaction;
1153
- return Object.freeze({
1154
- ...rest,
1155
- chain: Object.freeze({ ...transaction.chain }),
1156
- instructions: normalizeSolanaInstructions(transaction.instructions),
1157
- ...(lookupTables ? { addressLookupTables: lookupTables } : {}),
1158
- });
1159
- }
1160
- if (isSameChainSolanaOrigin(transaction)) {
1161
- const request = transaction.tokenRequests[0];
1162
- return Object.freeze({
1163
- ...transaction,
1164
- chain: Object.freeze({ ...transaction.chain }),
1165
- tokenRequests: [Object.freeze({ ...request })],
1166
- ...(transaction.appFees
1167
- ? { appFees: Object.freeze({ ...transaction.appFees }) }
1168
- : {}),
1169
- ...(transaction.protocolFees
1170
- ? { protocolFees: Object.freeze({ ...transaction.protocolFees }) }
1171
- : {}),
1172
- });
1173
- }
1174
- if ('targetChain' in transaction &&
1175
- transaction.targetChain !== undefined &&
1176
- 'kind' in transaction.targetChain &&
1177
- transaction.targetChain.kind === 'svm' &&
1178
- transaction.recipient === undefined &&
1179
- config.solana &&
1180
- 'address' in config.solana) {
1181
- return Object.freeze({
1182
- ...transaction,
1183
- recipient: config.solana.address,
1184
- });
1185
- }
1186
- return Object.freeze({ ...transaction });
1187
- }
1188
536
  function narrowQuoterPin(derived, explicit) {
1189
537
  if (!explicit)
1190
538
  return derived;
@@ -1196,13 +544,7 @@ function narrowQuoterPin(derived, explicit) {
1196
544
  : derived.include.filter((quoter) => !explicit.exclude.includes(quoter));
1197
545
  return { include: narrowed };
1198
546
  }
1199
- export function adaptTransaction(context, transaction, hyperCoreAction, automaticSourceChainIds) {
1200
- const nonEvmOrigin = 'chain' in transaction && transaction.chain && 'kind' in transaction.chain
1201
- ? transaction.chain.kind
1202
- : transaction.sourceChains?.find((chain) => 'kind' in chain)?.kind;
1203
- if (nonEvmOrigin) {
1204
- throw new UnsupportedAccountCapabilityError('Non-EVM origin execution is not supported yet. Use a viem EVM chain as the managed source.', { vm: nonEvmOrigin });
1205
- }
547
+ export function adaptTransaction(context, transaction, hyperCoreAction) {
1206
548
  const destination = 'chain' in transaction
1207
549
  ? getChainReference(transaction.chain.id)
1208
550
  : 'kind' in transaction.targetChain
@@ -1211,7 +553,7 @@ export function adaptTransaction(context, transaction, hyperCoreAction, automati
1211
553
  const destinationChainId = destination.kind === 'evm' ? destination.id : undefined;
1212
554
  const sourceChains = 'chain' in transaction
1213
555
  ? [getChainReference(transaction.chain.id)]
1214
- : (transaction.sourceChains?.map((chain) => getChainReference(chain.id)) ?? automaticSourceChainIds?.map(getChainReference));
556
+ : transaction.sourceChains?.map((chain) => getChainReference(chain.id));
1215
557
  const evmSources = sourceChains?.flatMap((chain) => chain.kind === 'evm' ? [chain] : []);
1216
558
  return {
1217
559
  destination,
@@ -1386,12 +728,9 @@ function adaptSessionSelection(transaction, chains) {
1386
728
  ]));
1387
729
  }
1388
730
  const chainIds = new Set(chains.flatMap((chain) => chain.kind === 'evm' && chain.id !== undefined ? [chain.id] : []));
1389
- if ('chain' in transaction && !('kind' in transaction.chain)) {
731
+ if ('chain' in transaction)
1390
732
  chainIds.add(transaction.chain.id);
1391
- }
1392
- if ('targetChain' in transaction &&
1393
- transaction.targetChain &&
1394
- 'id' in transaction.targetChain) {
733
+ if ('targetChain' in transaction && 'id' in transaction.targetChain) {
1395
734
  chainIds.add(transaction.targetChain.id);
1396
735
  }
1397
736
  return Object.fromEntries([...chainIds].map((chainId) => [
@@ -1405,18 +744,11 @@ function adaptSessionSelection(transaction, chains) {
1405
744
  function adaptSourceAssets(sourceAssets, chainIds) {
1406
745
  if (!sourceAssets)
1407
746
  return chainIds ? { chainIds } : undefined;
1408
- const eligible = chainIds ? new Set(chainIds) : undefined;
1409
- const assertEligible = (chainId) => {
1410
- if (eligible && !eligible.has(chainId)) {
1411
- throw new UnsupportedAccountCapabilityError(`Source assets reference chain ${chainId}, which is outside the eligible source scope.`, { chainId });
1412
- }
1413
- };
1414
747
  if (Array.isArray(sourceAssets)) {
1415
748
  if (sourceAssets.length > 0 && typeof sourceAssets[0] === 'object') {
1416
749
  const chainTokens = {};
1417
750
  const chainTokenAmounts = {};
1418
751
  for (const item of sourceAssets) {
1419
- assertEligible(item.chain.id);
1420
752
  const token = normalizeTokenAddress(item.address, item.chain.id, false);
1421
753
  if (item.amount === undefined)
1422
754
  (chainTokens[item.chain.id] ??= []).push(token);
@@ -1439,8 +771,7 @@ function adaptSourceAssets(sourceAssets, chainIds) {
1439
771
  }
1440
772
  // ChainTokenMap: validate every per-chain list too, so symbols can't slip
1441
773
  // through this input the way they can't through tokenRequests / ExactInputConfig.
1442
- for (const [chainId, tokens] of Object.entries(sourceAssets)) {
1443
- assertEligible(Number(chainId));
774
+ for (const tokens of Object.values(sourceAssets)) {
1444
775
  validateTokenAddresses(tokens);
1445
776
  }
1446
777
  return { chainTokens: sourceAssets };