From 53341cb8792fa06078c2c163547cd45bf3bf4a19 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Mon, 2 Mar 2026 14:09:48 +0100 Subject: [PATCH 01/14] feat: recipient field --- src/lib/components/GetQuote.svelte | 5 +- src/lib/libraries/intent.ts | 937 +++++++++++++++++++++++++++++ src/lib/screens/IssueIntent.svelte | 18 +- src/lib/state.svelte.ts | 1 + 4 files changed, 958 insertions(+), 3 deletions(-) create mode 100644 src/lib/libraries/intent.ts diff --git a/src/lib/components/GetQuote.svelte b/src/lib/components/GetQuote.svelte index bf78c89..5a59264 100644 --- a/src/lib/components/GetQuote.svelte +++ b/src/lib/components/GetQuote.svelte @@ -10,6 +10,7 @@ inputTokens, outputTokens = $bindable(), account, + recipient, mainnet }: { exclusiveFor: string; @@ -17,6 +18,7 @@ inputTokens: AppTokenContext[]; outputTokens: AppTokenContext[]; account: () => `0x${string}`; + recipient: () => `0x${string}` | undefined; mainnet: boolean; } = $props(); @@ -33,6 +35,7 @@ ) : undefined; + const receiver = recipient() ?? account(); const response = await intentApi.getQuotes({ user: account(), userChainId: inputTokens[0].token.chainId, @@ -47,7 +50,7 @@ }), outputs: outputTokens.map(({ token }) => { return { - receiver: account(), + receiver: receiver, asset: token.address, chainId: token.chainId, amount: 0n diff --git a/src/lib/libraries/intent.ts b/src/lib/libraries/intent.ts new file mode 100644 index 0000000..2e00bf7 --- /dev/null +++ b/src/lib/libraries/intent.ts @@ -0,0 +1,937 @@ +import { encodeAbiParameters, encodePacked, hashStruct, keccak256, parseAbiParameters } from "viem"; +import type { + BatchCompact, + CompactMandate, + Element, + MandateOutput, + MultichainCompact, + MultichainOrder, + MultichainOrderComponent, + NoSignature, + Signature, + StandardOrder +} from "../../types"; +import { COMPACT_ABI } from "../abi/compact"; +import { + chainMap, + clients, + COIN_FILLER, + COMPACT, + getChainName, + getOracle, + INPUT_SETTLER_COMPACT_LIFI, + INPUT_SETTLER_ESCROW_LIFI, + MULTICHAIN_INPUT_SETTLER_COMPACT, + MULTICHAIN_INPUT_SETTLER_ESCROW, + type chain, + type Verifier, + type WC +} from "../config"; +import { ResetPeriod, toId } from "../utils/idLib"; +import { compact_type_hash, compactTypes } from "../utils/typedMessage"; +import { addressToBytes32 } from "../utils/convert"; +import { SETTLER_ESCROW_ABI } from "../abi/escrow"; +import type { TokenContext } from "$lib/state.svelte"; +import { MULTICHAIN_SETTLER_ESCROW_ABI } from "$lib/abi/multichain_escrow"; +import { SETTLER_COMPACT_ABI } from "$lib/abi/settlercompact"; +import { toHex } from "$lib/utils/interopableAddresses"; +import { MULTICHAIN_SETTLER_COMPACT_ABI } from "$lib/abi/multichain_compact"; + +type Lock = { + lockTag: `0x${string}`; + token: `0x${string}`; + amount: bigint; +}; + +export type EscrowLock = { + type: "escrow"; +}; + +export type CompactLock = { + type: "compact"; + resetPeriod: ResetPeriod; + allocatorId: string; +}; + +export type CreateIntentOptionsEscrow = { + recipient: string; + exclusiveFor: string; + inputTokens: TokenContext[]; + outputTokens: TokenContext[]; + verifier: Verifier; + account: () => `0x${string}`; + lock: EscrowLock; +}; + +export type CreateIntentOptionsCompact = { + recipient: string; + exclusiveFor: string; + inputTokens: TokenContext[]; + outputTokens: TokenContext[]; + verifier: Verifier; + account: () => `0x${string}`; + lock: CompactLock; +}; + +export type CreateIntentOptions = CreateIntentOptionsEscrow | CreateIntentOptionsCompact; + +function findChain(chainId: bigint) { + for (const [name, data] of Object.entries(chainMap)) { + if (BigInt(data.id) === chainId) { + return chainMap[name as chain]; + } + } + return undefined; +} + +function selectAllBut(arr: T[], index: number): T[] { + return [...arr.slice(0, index), ...arr.slice(index + 1, arr.length)]; +} + +function encodeOutputs(outputs: MandateOutput[]) { + return encodeAbiParameters( + parseAbiParameters( + "(bytes32 oracle, bytes32 settler, uint256 chainId, bytes32 token, uint256 amount, bytes32 recipient, bytes callbackData, bytes context)[]" + ), + [outputs] + ); +} + +const ONE_MINUTE = 60; +const ONE_HOUR = 60 * ONE_MINUTE; +const ONE_DAY = 24 * ONE_HOUR; + +/** + * @notice Class representing a Li.Fi Intent. Contains intent abstractions and helpers. + */ +export class Intent { + private lock: EscrowLock | CompactLock; + + // User facing order options + private user: () => `0x${string}`; + private recipient: `0x${string}`; + private inputs: TokenContext[]; + private outputs: TokenContext[]; + private verifier: Verifier; + + private exclusiveFor?: `0x${string}`; + + private _nonce?: bigint; + + private expiry = ONE_DAY; + private fillDeadline = 2 * ONE_HOUR; + + constructor(opts: CreateIntentOptionsEscrow | CreateIntentOptionsCompact) { + this.lock = opts.lock; + + this.user = opts.account; + this.recipient = this.normalizeRecipient(opts.recipient); + this.inputs = opts.inputTokens; + this.outputs = opts.outputTokens; + this.verifier = opts.verifier; + + this.exclusiveFor = this.normalizeExclusiveFor(opts.exclusiveFor); + } + + private normalizeRecipient(recipient: string): `0x${string}` { + const trimmed = recipient.trim(); + const normalized = trimmed.toLowerCase(); + if (!/^0x[0-9a-f]{40}$/.test(normalized)) { + throw new Error(`Recipient not formatted correctly: ${recipient}`); + } + return normalized as `0x${string}`; + } + + private normalizeExclusiveFor(exclusiveFor: string): `0x${string}` | undefined { + const trimmed = exclusiveFor.trim(); + if (trimmed.length === 0) return undefined; + const normalized = trimmed.toLowerCase(); + if (!/^0x[0-9a-f]{40}$/.test(normalized)) { + throw new Error(`ExclusiveFor not formatted correctly ${exclusiveFor}`); + } + return normalized as `0x${string}`; + } + + numInputChains() { + const tokenChains = this.inputs.map(({ token }) => token.chain); + return [...new Set(tokenChains)].length; + } + + isMultichain() { + return this.numInputChains() > 1; + } + + isSameChain() { + // Multichain intents cannot be same chain. Normal "Output oracle" will be used. + if (this.isMultichain()) return false; + + // Only 1 input chain is used. + const inputChain = this.inputs[0].token.chain; + const outputChains = this.outputs.map((o) => o.token.chain); + const numOutputChains = [...new Set(outputChains)].length; + if (numOutputChains > 1) return false; + // Only 1 output chain is used. + const outputChain = this.outputs[0].token.chain; + return inputChain === outputChain; + } + + nonce() { + if (this._nonce) return this._nonce; + this._nonce = BigInt(Math.floor(Math.random() * 2 ** 32)); + return this._nonce; + } + + inputSettler(multichain: boolean) { + if (this.lock.type === "compact" && multichain === false) return INPUT_SETTLER_COMPACT_LIFI; + if (this.lock.type === "compact" && multichain === true) + return MULTICHAIN_INPUT_SETTLER_COMPACT; + if (this.lock.type === "escrow" && multichain === false) return INPUT_SETTLER_ESCROW_LIFI; + if (this.lock.type === "escrow" && multichain === true) return MULTICHAIN_INPUT_SETTLER_ESCROW; + + throw new Error(`Not supported | multichain: ${multichain}, type: ${this.lock.type}`); + } + + encodeOutputs(currentTime: number) { + // Get the current epoch timestamp: + currentTime; + const ONE_MINUTE = 60; + + let context: `0x${string}` = "0x"; + if (this.exclusiveFor) { + const paddedExclusiveFor: `0x${string}` = `0x${this.exclusiveFor.replace("0x", "").padStart(64, "0")}`; + context = encodePacked( + ["bytes1", "bytes32", "uint32"], + ["0xe0", paddedExclusiveFor, currentTime + ONE_MINUTE] + ); + } + + const outputSettler = COIN_FILLER; + const sameChain = this.isSameChain(); + + return this.outputs.map(({ token, amount }) => { + const outputOracle = sameChain + ? addressToBytes32(outputSettler) + : addressToBytes32(getOracle(this.verifier, token.chain)!); + return { + oracle: outputOracle, + settler: addressToBytes32(outputSettler), + chainId: BigInt(chainMap[token.chain].id), + token: addressToBytes32(token.address), + amount: amount, + recipient: addressToBytes32(this.recipient), + callbackData: "0x", + context + }; + }) as MandateOutput[]; + } + + singlechain() { + if (this.isMultichain()) + throw new Error(`Not supported as single chain with ${this.numInputChains()} chains`); + + const inputChain = this.inputs[0].token.chain; + + const inputs: [bigint, bigint][] = this.inputs.map(({ token, amount }) => [ + this.lock.type === "compact" + ? toId(true, this.lock.resetPeriod, this.lock.allocatorId, token.address) + : BigInt(token.address), + amount + ]); + + const currentTime = Math.floor(Date.now() / 1000); + + const inputOracle = this.isSameChain() ? COIN_FILLER : getOracle(this.verifier, inputChain)!; + + const order: StandardOrder = { + user: this.user(), + nonce: this.nonce(), + originChainId: BigInt(chainMap[inputChain].id), + fillDeadline: currentTime + this.fillDeadline, + expires: currentTime + this.expiry, + inputOracle: inputOracle, + inputs: inputs, + outputs: this.encodeOutputs(currentTime) + }; + + return new StandardOrderIntent(this.inputSettler(false), order); + } + + multichain() { + const currentTime = Math.floor(Date.now() / 1000); + + // TODO: Fix before release. The input oracle is not the same on every chain. + const inputOracle = getOracle(this.verifier, this.inputs[0].token.chain)!; + + // Get all unique chains and then get all inputs for each chain. + const inputs: { chainId: bigint; inputs: [bigint, bigint][] }[] = [ + ...new Set(this.inputs.map(({ token }) => token.chain)) + ].map((chain) => { + const chainInputs = this.inputs.filter(({ token }) => token.chain === chain); + + return { + chainId: BigInt(chainMap[chain].id), + inputs: chainInputs.map(({ token, amount }) => [ + this.lock.type === "compact" + ? toId(true, this.lock.resetPeriod, this.lock.allocatorId, token.address) + : BigInt(token.address), + amount + ]) + }; + }); + + const order: MultichainOrder = { + user: this.user(), + nonce: this.nonce(), + fillDeadline: currentTime + this.fillDeadline, + expires: currentTime + this.expiry, + inputOracle: inputOracle, + outputs: this.encodeOutputs(currentTime), + inputs: inputs + }; + + return new MultichainOrderIntent(this.inputSettler(true), order, this.lock); + } + + order() { + if (this.isMultichain()) return this.multichain(); + return this.singlechain(); + } +} + +/// @notice Helper function that allows you to provide an order and it will correctly generate the appropriate order. +export function orderToIntent(options: { + inputSettler: `0x${string}`; + order: StandardOrder; + lock?: { type: string }; +}): StandardOrderIntent; +export function orderToIntent(options: { + inputSettler: `0x${string}`; + order: MultichainOrder; + lock?: { type: string }; +}): MultichainOrderIntent; +export function orderToIntent(options: { + inputSettler: `0x${string}`; + order: StandardOrder | MultichainOrder; + lock?: { type: string }; +}): StandardOrderIntent | MultichainOrderIntent; +export function orderToIntent(options: { + inputSettler: `0x${string}`; + order: StandardOrder | MultichainOrder; + lock?: { type: string }; +}): StandardOrderIntent | MultichainOrderIntent { + const { inputSettler, order, lock } = options; + // Use presence of originChainId to discriminate StandardOrder vs MultichainOrder + if ("originChainId" in order) { + return new StandardOrderIntent(inputSettler, order as StandardOrder); + } + return new MultichainOrderIntent(inputSettler, order as MultichainOrder, lock); +} + +export class StandardOrderIntent { + inputSettler: `0x${string}`; + order: StandardOrder; + + constructor(inputSetter: `0x${string}`, order: StandardOrder) { + this.inputSettler = inputSetter; + this.order = order; + } + + // -- Order Representations -- // + + /** + * @notice Returns for logging + */ + asOrder(): StandardOrder { + return this.order; + } + + /** + * @notice Returns the order as a StandardOrder. + * @returns Order as StandardOrder + */ + asStandardOrder(): StandardOrder { + return this.order; + } + + /** + * @notice Returns the order as a BatchCompact. + * @returns Order as BatchCompact (signed object for Compact) + */ + asBatchCompact(): BatchCompact { + const { order } = this; + const mandate: CompactMandate = { + fillDeadline: order.fillDeadline, + inputOracle: order.inputOracle, + outputs: order.outputs + }; + const commitments = order.inputs.map(([tokenId, amount]) => { + const lockTag: `0x${string}` = `0x${toHex(tokenId, 32).slice(0, 12 * 2)}`; + const token: `0x${string}` = `0x${toHex(tokenId, 32).slice(12 * 2, 32 * 2)}`; + return { + lockTag, + token, + amount + }; + }); + return { + arbiter: INPUT_SETTLER_COMPACT_LIFI, + sponsor: order.user, + nonce: order.nonce, + expires: BigInt(order.expires), + commitments, + mandate + }; + } + + inputChains(): bigint[] { + return [this.order.originChainId]; + } + + orderId(): `0x${string}` { + return keccak256( + encodePacked( + [ + "uint256", + "address", + "address", + "uint256", + "uint32", + "uint32", + "address", + "bytes32", + "bytes" + ], + [ + this.order.originChainId, + this.inputSettler, + this.order.user, + this.order.nonce, + this.order.expires, + this.order.fillDeadline, + this.order.inputOracle, + keccak256(encodePacked(["uint256[2][]"], [this.order.inputs])), + encodeOutputs(this.order.outputs) + ] + ) + ); + } + + // -- Escrow Helpers -- // + + /** + * @notice Opens an intent using the escrow input settler by depositing into it. + * @param account Account that calls open. + * @param walletClient Wallet client for sending the call to. + * @returns transactionHash for the on-chain call. + */ + async openEscrow(account: `0x${string}`, walletClient: WC): Promise<[`0x${string}`]> { + const chain = findChain(this.order.originChainId); + walletClient.switchChain({ id: Number(this.order.originChainId) }); + if (!chain) + throw new Error("Chain not found for chainId " + this.order.originChainId.toString()); + return [ + await walletClient.writeContract({ + chain, + account, + address: INPUT_SETTLER_ESCROW_LIFI, + abi: SETTLER_ESCROW_ABI, + functionName: "open", + args: [this.order] + }) + ]; + } + + // -- Compact Helpers -- // + + compactClaimHash(): `0x${string}` { + const claimHash = hashStruct({ + data: this.asBatchCompact(), + types: compactTypes, + primaryType: "BatchCompact" + }); + return claimHash; + } + + signCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { + const chainId = this.order.originChainId; + return walletClient.signTypedData({ + account, + domain: { + name: "The Compact", + version: "1", + chainId, + verifyingContract: COMPACT + } as const, + types: compactTypes, + primaryType: "BatchCompact", + message: this.asBatchCompact() + }); + } + + depositAndRegisterCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { + const chain = findChain(this.order.originChainId); + if (!chain) + throw new Error("Chain not found for chainId " + this.order.originChainId.toString()); + return walletClient.writeContract({ + chain, + account, + address: COMPACT, + abi: COMPACT_ABI, + functionName: "batchDepositAndRegisterMultiple", + args: [this.order.inputs, [[this.compactClaimHash(), compact_type_hash]]] + }); + } + + async finalise(options: { + sourceChain: chain; + account: `0x${string}`; + walletClient: WC; + solveParams: { timestamp: number; solver: `0x${string}` }[]; + signatures: { + sponsorSignature: Signature | NoSignature; + allocatorSignature: Signature | NoSignature; + }; + }) { + const { sourceChain, account, walletClient, solveParams, signatures } = options; + const actionChain = chainMap[sourceChain]; + if (actionChain.id !== Number(this.order.originChainId)) + throw new Error( + `Origin chain id and action ID does not match: ${this.order.originChainId}, ${actionChain.id}` + ); + + if (this.inputSettler.toLowerCase() === INPUT_SETTLER_ESCROW_LIFI.toLowerCase()) { + return await walletClient.writeContract({ + chain: actionChain, + account: account, + address: this.inputSettler, + abi: SETTLER_ESCROW_ABI, + functionName: "finalise", + args: [this.order, solveParams, addressToBytes32(account), "0x"] + }); + } else if (this.inputSettler.toLowerCase() === INPUT_SETTLER_COMPACT_LIFI.toLowerCase()) { + // Check whether or not we have a signature. + const { sponsorSignature, allocatorSignature } = signatures; + console.log({ + sponsorSignature, + allocatorSignature + }); + const combinedSignatures = encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ + sponsorSignature.payload ?? "0x", + allocatorSignature.payload + ]); + return await walletClient.writeContract({ + chain: actionChain, + account: account, + address: this.inputSettler, + abi: SETTLER_COMPACT_ABI, + functionName: "finalise", + args: [this.order, combinedSignatures, solveParams, addressToBytes32(account), "0x"] + }); + } else { + throw new Error(`Could not detect settler type ${this.inputSettler}`); + } + } +} + +export class MultichainOrderIntent { + lock?: { type: string } | EscrowLock | CompactLock; + + // Notice that this has to be the same address on every chain. + inputSettler: `0x${string}`; + order: MultichainOrder; + + constructor(inputSetter: `0x${string}`, order: MultichainOrder, lock?: { type: string }) { + this.inputSettler = inputSetter; + this.order = order; + + const isCompact = + this.inputSettler === INPUT_SETTLER_COMPACT_LIFI || + this.inputSettler === MULTICHAIN_INPUT_SETTLER_COMPACT; + + this.lock = lock ?? { type: isCompact ? "compact" : "escrow" }; + } + + selfTest() { + this.asOrder(); + this.inputChains(); + this.asComponents(); + + this.orderId(); + } + + /** + * @notice Returns for logging + */ + asOrder(): MultichainOrder { + return this.order; + } + + inputChains(): bigint[] { + return [...new Set(this.order.inputs.map((i) => i.chainId))]; + } + + orderId(): `0x${string}` { + // We need a random order components. + const components = this.asComponents(); + const computedOrderIds = components.map((c) => + this.lock?.type === "escrow" + ? MultichainOrderIntent.escrowOrderId(this.inputSettler, c.orderComponent, c.chainId) + : MultichainOrderIntent.compactOrderid(this.inputSettler, c.orderComponent, c.chainId) + ); + + const orderId = computedOrderIds[0]; + computedOrderIds.map((v) => { + if (v !== orderId) throw new Error(`Order ids are not equal ${computedOrderIds}`); + }); + if (this.lock?.type === "compact") { + const multichainCompactHash = hashStruct({ + data: this.asMultichainBatchCompact(), + types: compactTypes, + primaryType: "MultichainCompact" + }); + if (multichainCompactHash !== orderId) + throw new Error( + `MultichainCompact does not match orderId, ${multichainCompactHash} ${orderId}` + ); + } + return orderId; + } + + async orderIdCheck() { + const components = this.asComponents(); + const computedOrderId = this.orderId(); + const onChainOrderIds = await Promise.all( + components.map(async (component) => { + const onChainId = await clients[getChainName(component.chainId)].readContract({ + address: this.inputSettler, + abi: MULTICHAIN_SETTLER_COMPACT_ABI, + functionName: "orderIdentifier", + args: [component.orderComponent] + }); + return onChainId; + }) + ); + console.log({ computedOrderId, onChainOrderIds }); + } + + static escrowOrderId( + inputSettler: `0x${string}`, + orderComponent: MultichainOrderComponent, + _: bigint + ) { + return keccak256( + encodePacked( + ["address", "address", "uint256", "uint32", "uint32", "address", "bytes32", "bytes"], + [ + inputSettler, + orderComponent.user, + orderComponent.nonce, + orderComponent.expires, + orderComponent.fillDeadline, + orderComponent.inputOracle, + MultichainOrderIntent.constructInputHash( + orderComponent.chainIdField, + orderComponent.chainIndex, + orderComponent.inputs, + orderComponent.additionalChains + ), + encodeOutputs(orderComponent.outputs) + ] + ) + ); + } + + static compactOrderid( + inputSettler: `0x${string}`, + orderComponent: MultichainOrderComponent, + chainId: bigint + ) { + const MULTICHAIN_COMPACT_TYPEHASH_WITH_WITNESS = keccak256( + encodePacked( + ["string"], + [ + "MultichainCompact(address sponsor,uint256 nonce,uint256 expires,Element[] elements)Element(address arbiter,uint256 chainId,Lock[] commitments,Mandate mandate)Lock(bytes12 lockTag,address token,uint256 amount)Mandate(uint32 fillDeadline,address inputOracle,MandateOutput[] outputs)MandateOutput(bytes32 oracle,bytes32 settler,uint256 chainId,bytes32 token,uint256 amount,bytes32 recipient,bytes callbackData,bytes context)" + ] + ) + ); + const { fillDeadline, inputOracle, outputs, inputs } = orderComponent; + const mandate: CompactMandate = { + fillDeadline, + inputOracle, + outputs + }; + const element: Element = { + arbiter: inputSettler, + chainId: chainId, + commitments: MultichainOrderIntent.inputsToLocks(inputs), + mandate + }; + + const elementHash = hashStruct({ + types: compactTypes, + primaryType: "Element", + data: element + }); + + const elementHashes = [ + ...orderComponent.additionalChains.slice(0, Number(orderComponent.chainIndex)), + elementHash, + ...orderComponent.additionalChains.slice(Number(orderComponent.chainIndex)) + ]; + + return keccak256( + encodeAbiParameters( + parseAbiParameters(["bytes32", "address", "uint256", "uint256", "bytes32"]), + [ + MULTICHAIN_COMPACT_TYPEHASH_WITH_WITNESS, + orderComponent.user, + orderComponent.nonce, + BigInt(orderComponent.expires), + keccak256(encodePacked(["bytes32[]"], [elementHashes])) + ] + ) + ); + } + + static hashInputs(chainId: bigint, inputs: [bigint, bigint][]) { + return keccak256(encodePacked(["uint256", "uint256[2][]"], [chainId, inputs])); + } + + static constructInputHash( + inputsChainId: bigint, + chainIndex: bigint, + inputs: [bigint, bigint][], + additionalChains: `0x${string}`[] + ) { + const inputHash = MultichainOrderIntent.hashInputs(inputsChainId, inputs); + const numSegments = additionalChains.length + 1; + if (numSegments <= chainIndex) + throw new Error(`ChainIndexOutOfRange(${chainIndex},${numSegments})`); + const claimStructure: `0x${string}`[] = []; + for (let i = 0; i < numSegments; ++i) { + const additionalChainsIndex = i > chainIndex ? i - 1 : i; + const inputHashElement = + chainIndex == BigInt(i) ? inputHash : additionalChains[additionalChainsIndex]; + claimStructure[i] = inputHashElement; + } + return keccak256(encodePacked(["bytes32[]"], [claimStructure])); + } + + static inputsToLocks(inputs: [bigint, bigint][]): Lock[] { + return inputs.map((input) => { + const bytes32 = toHex(input[0], 32); + return { + lockTag: `0x${bytes32.slice(0, 12 * 2)}`, + token: `0x${bytes32.slice(12 * 2, 32 * 2)}`, + amount: input[1] + }; + }); + } + + secondariesEcsrow(): { chainIdField: bigint; additionalChains: `0x${string}`[] }[] { + const inputsHash: `0x${string}`[] = this.order.inputs.map((input) => + keccak256(encodePacked(["uint256", "uint256[2][]"], [input.chainId, input.inputs])) + ); + return this.order.inputs.map((v, i) => { + return { + chainIdField: v.chainId, + additionalChains: selectAllBut(inputsHash, i) + }; + }); + } + + asCompactElements() { + const { fillDeadline, inputOracle, outputs, inputs } = this.order; + const mandate: CompactMandate = { + fillDeadline, + inputOracle, + outputs + }; + return inputs.map((inputs) => { + const element: Element = { + arbiter: this.inputSettler, + chainId: inputs.chainId, + commitments: MultichainOrderIntent.inputsToLocks(inputs.inputs), + mandate + }; + return element; + }); + } + + secondariesCompact(): { chainIdField: bigint; additionalChains: `0x${string}`[] }[] { + const { inputs } = this.order; + const elements = this.asCompactElements().map((element) => { + const hash = hashStruct({ + types: compactTypes, + primaryType: "Element", + data: element + }); + return hash; + }); + return inputs.map((_, i) => { + return { + chainIdField: inputs[0].chainId, + additionalChains: selectAllBut(elements, i) + }; + }); + } + + asComponents(): { chainId: bigint; orderComponent: MultichainOrderComponent }[] { + const { inputs, user, nonce, expires, fillDeadline, inputOracle, outputs } = this.order; + if (!this.lock) throw new Error(`No lock provided, cannot compute secondaries.`); + const secondaries = + this.lock.type == "escrow" ? this.secondariesEcsrow() : this.secondariesCompact(); + const components: { chainId: bigint; orderComponent: MultichainOrderComponent }[] = []; + for (let i = 0; i < inputs.length; ++i) { + const { chainIdField, additionalChains } = secondaries[i]; + + const orderComponent: MultichainOrderComponent = { + user: user, + nonce: nonce, + chainIdField: chainIdField, + chainIndex: BigInt(i), + expires: expires, + fillDeadline: fillDeadline, + inputOracle: inputOracle, + inputs: inputs[i].inputs, + outputs: outputs, + additionalChains: additionalChains + }; + components.push({ chainId: inputs[i].chainId, orderComponent }); + } + return components; + } + + // -- Compact Helpers -- // + + asMultichainBatchCompact(): MultichainCompact { + const { order } = this; + const mandate: CompactMandate = { + fillDeadline: order.fillDeadline, + inputOracle: order.inputOracle, + outputs: order.outputs + }; + const result = { + sponsor: order.user, + nonce: order.nonce, + expires: BigInt(order.expires), + elements: this.asCompactElements(), + mandate + }; + return result; + } + + compactClaimHash(): `0x${string}` { + const claimHash = hashStruct({ + data: this.asMultichainBatchCompact(), + types: compactTypes, + primaryType: "MultichainCompact" + }); + return claimHash; + } + + signCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { + this.selfTest(); + const chainId = this.order.inputs[0].chainId; + return walletClient.signTypedData({ + account, + domain: { + name: "The Compact", + version: "1", + chainId, + verifyingContract: COMPACT + } as const, + types: compactTypes, + primaryType: "MultichainCompact", + message: this.asMultichainBatchCompact() + }); + } + + // This code is depreciated and needs to be updated. + async openEscrow(account: `0x${string}`, walletClient: WC) { + this.selfTest(); + const components = this.asComponents(); + const results: `0x${string}`[] = []; + for (const { chainId, orderComponent } of components) { + const chain = findChain(chainId)!; + walletClient.switchChain({ id: chain.id }); + results.push( + await walletClient.writeContract({ + chain, + account, + address: this.inputSettler, + abi: MULTICHAIN_SETTLER_ESCROW_ABI, + functionName: "open", + args: [orderComponent] + }) + ); + console.log(results); + } + return results; + } + + async finalise(options: { + sourceChain: chain; + account: `0x${string}`; + walletClient: WC; + solveParams: { timestamp: number; solver: `0x${string}` }[]; + signatures: { + sponsorSignature: Signature | NoSignature; + allocatorSignature: Signature | NoSignature; + }; + }) { + this.asMultichainBatchCompact(); + const { sourceChain, account, walletClient, solveParams, signatures } = options; + const actionChain = chainMap[sourceChain]; + const inputChainIds = this.inputChains().map((v) => Number(v)); + if (!inputChainIds.includes(actionChain.id)) + throw new Error( + `Action chain must be one of input chains for finalise: ${inputChainIds}, action=${actionChain.id}` + ); + // Get all components for our chain. + const components = this.asComponents().filter((c) => Number(c.chainId) === actionChain.id); + if (components.length === 0) { + throw new Error( + `No multichain order component found for action chain ${actionChain.id} (${sourceChain}).` + ); + } + + for (const { orderComponent, chainId } of components) { + if (this.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_ESCROW.toLowerCase()) { + return await walletClient.writeContract({ + chain: actionChain, + account: account, + address: this.inputSettler, + abi: MULTICHAIN_SETTLER_ESCROW_ABI, + functionName: "finalise", + args: [orderComponent, solveParams, addressToBytes32(account), "0x"] + }); + } else if ( + this.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_COMPACT.toLowerCase() + ) { + const { sponsorSignature, allocatorSignature } = signatures; + console.log({ + orderComponent, + sponsorSignature, + allocatorSignature + }); + + const combinedSignatures = encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ + sponsorSignature.payload ?? "0x", + allocatorSignature.payload + ]); + return await walletClient.writeContract({ + chain: actionChain, + account: account, + address: this.inputSettler, + abi: MULTICHAIN_SETTLER_COMPACT_ABI, + functionName: "finalise", + args: [orderComponent, combinedSignatures, solveParams, addressToBytes32(account), "0x"] + }); + } else { + throw new Error(`Could not detect settler type ${this.inputSettler}`); + } + } + throw new Error(`Failed to finalise multichain order on chain ${sourceChain}.`); + } +} diff --git a/src/lib/screens/IssueIntent.svelte b/src/lib/screens/IssueIntent.svelte index 167d326..dcc0564 100644 --- a/src/lib/screens/IssueIntent.svelte +++ b/src/lib/screens/IssueIntent.svelte @@ -161,6 +161,8 @@ return uniqueChains.length; }); + const recipientValid = $derived(isAddress(store.recipient, { strict: false })); + const sameChain = $derived.by(() => { if (numInputChains > 1) return false; const inputChain = store.inputTokens[0].token.chainId; @@ -210,6 +212,7 @@ inputTokens={store.inputTokens} bind:outputTokens={store.outputTokens} {account} + recipient={() => (recipientValid ? (store.recipient as `0x${string}`) : undefined)} > {/snippet} @@ -276,6 +279,17 @@
+
+ Recipient + 0 && !recipientValid ? "error" : "default"} + bind:value={store.recipient} + /> +
Verifier {#if sameChain} @@ -313,13 +327,13 @@
- {#if !true} + {#if !recipientValid} {:else if !allowanceCheck} diff --git a/src/lib/state.svelte.ts b/src/lib/state.svelte.ts index 145bc99..9ffb463 100644 --- a/src/lib/state.svelte.ts +++ b/src/lib/state.svelte.ts @@ -272,6 +272,7 @@ class Store { intentType = $state<"escrow" | "compact">("escrow"); allocatorId = $state(ALWAYS_OK_ALLOCATOR); verifier = $state("polymer"); + recipient: string = $state(""); exclusiveFor: string = $state(""); useExclusiveForQuoteRequest = $state(false); From e1f7b81e475c896a2a15cc2c09eef9ffb34fb68b Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Mon, 2 Mar 2026 22:13:02 +0100 Subject: [PATCH 02/14] feat: evm to solana intent --- package.json | 5 +- src/lib/components/InputTokenModal.svelte | 32 ++++++---- src/lib/config.ts | 46 ++++++++++++-- src/lib/libraries/intent.ts | 49 ++++++++++++--- src/lib/screens/IssueIntent.svelte | 60 ++++++++++++++++-- src/lib/state.svelte.ts | 5 +- src/lib/utils/convert.ts | 75 +++++++++++++++++++++++ 7 files changed, 237 insertions(+), 35 deletions(-) create mode 100644 src/lib/utils/convert.ts diff --git a/package.json b/package.json index dbfc3dc..262428c 100644 --- a/package.json +++ b/package.json @@ -22,22 +22,24 @@ "devDependencies": { "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", + "@playwright/test": "^1.55.0", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^6.1.1", "@tailwindcss/vite": "^4.0.0", "@types/bun": "^1.3.8", - "@playwright/test": "^1.55.0", "drizzle-kit": "^0.31.9", "dotenv": "^17.2.3", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-svelte": "^3.0.0", "globals": "^16.0.0", + "husky": "9.1.7", "lint-staged": "16.1.0", "prettier": "3.4.2", "prettier-plugin-svelte": "3.3.3", "prettier-plugin-tailwindcss": "0.6.11", + "svelte": "^5.0.0", "svelte-check": "^4.0.0", "tailwindcss": "^4.0.0", @@ -54,6 +56,7 @@ "@wagmi/core": "^3.4.0", "axios": "^1.9.0", "base64-js": "^1.5.1", + "bs58": "^6.0.0", "drizzle-orm": "^0.45.1", "rxjs": "^7.8.2", "viem": "~2.45.1", diff --git a/src/lib/components/InputTokenModal.svelte b/src/lib/components/InputTokenModal.svelte index ea7bcf3..bd40871 100644 --- a/src/lib/components/InputTokenModal.svelte +++ b/src/lib/components/InputTokenModal.svelte @@ -1,5 +1,5 @@ + +{#if solanaWallet.connected && solanaWallet.publicKey} +
+ + ◎ {truncate(solanaWallet.publicKey)} + + +
+{:else} +
+ + +
+ {#if error} +

{error}

+ {/if} +{/if} diff --git a/src/lib/config.ts b/src/lib/config.ts index 3f6efde..9c3ba44 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -1,4 +1,5 @@ import { createPublicClient, createWalletClient, custom, defineChain, fallback, http } from "viem"; +import { Connection } from "@solana/web3.js"; import { arbitrum, arbitrumSepolia, @@ -39,6 +40,8 @@ const solanaDevnet = defineChain({ }, testnet: true }); +export const solanaDevnetConnection = new Connection("https://api.devnet.solana.com", "confirmed"); + // catalyst-intent-svm program IDs (devnet) — from Anchor.toml export const SOLANA_INTENTS_PROTOCOL = "4SQaweUpT1LrRg1gh9sVEDL3Q4jZH3wxRi3qpz23SRpj" as const; export const SOLANA_OUTPUT_SETTLER_SIMPLE = "8yt6Q3Gj8QCAqRVHQULckMf4rWSKQgN6SKVy9QTY5uWe" as const; diff --git a/src/lib/libraries/token.ts b/src/lib/libraries/token.ts index b4ae255..c242fec 100644 --- a/src/lib/libraries/token.ts +++ b/src/lib/libraries/token.ts @@ -2,6 +2,7 @@ import { maxUint256 } from "viem"; import { COMPACT_ABI } from "../abi/compact"; import { ERC20_ABI } from "../abi/erc20"; import { ADDRESS_ZERO, clients, COMPACT } from "../config"; +import { Connection, PublicKey } from "@solana/web3.js"; import { ResetPeriod, toId } from "@lifi/intent"; export async function getBalance( @@ -42,6 +43,34 @@ export function getAllowance(contract: `0x${string}`) { }; } +export async function getSolanaBalance( + userBase58: string | undefined, + asset: `0x${string}`, + connection: Connection +): Promise { + if (!userBase58) return 0n; + try { + const userPubkey = new PublicKey(userBase58); + if (asset === ADDRESS_ZERO) { + const lamports = await connection.getBalance(userPubkey); + return BigInt(lamports); + } + const hex = asset.replace("0x", ""); + const mintBytes = new Uint8Array(hex.length / 2); + for (let i = 0; i < hex.length; i += 2) mintBytes[i / 2] = parseInt(hex.slice(i, i + 2), 16); + const mintPubkey = new PublicKey(mintBytes); + const tokenAccounts = await connection.getParsedTokenAccountsByOwner(userPubkey, { + mint: mintPubkey + }); + if (tokenAccounts.value.length === 0) return 0n; + const amount = tokenAccounts.value[0].account.data.parsed.info.tokenAmount.amount; + return BigInt(amount); + } catch (e) { + console.error("getSolanaBalance failed", { userBase58, asset, error: e }); + return 0n; + } +} + export async function getCompactBalance( user: `0x${string}` | undefined, asset: `0x${string}`, diff --git a/src/lib/screens/IssueIntent.svelte b/src/lib/screens/IssueIntent.svelte index 958d109..e77f8b8 100644 --- a/src/lib/screens/IssueIntent.svelte +++ b/src/lib/screens/IssueIntent.svelte @@ -14,6 +14,7 @@ import OutputTokenModal from "$lib/components/OutputTokenModal.svelte"; import { ResetPeriod } from "@lifi/intent"; import type { AppCreateIntentOptions } from "$lib/appTypes"; + import SolanaWalletButton from "$lib/components/SolanaWalletButton.svelte"; const bigIntSum = (...nums: bigint[]) => nums.reduce((a, b) => a + b, 0n); const REQUIRED_INPUT_USDC_RAW = 100n; @@ -171,7 +172,9 @@ isAddress(store.recipient, { strict: false }) ); const solanaRecipientValid = $derived( - !hasSolanaOutput || isValidSolanaAddress(store.solanaRecipient) + !hasSolanaOutput || + store.solanaRecipient.trim().length === 0 || + isValidSolanaAddress(store.solanaRecipient) ); const recipientValid = $derived(evmRecipientValid && solanaRecipientValid); @@ -294,6 +297,12 @@
+
+ Solana Wallet + +
Verifier - {#if sameChain} - - - - {:else} - - - - - {/if} + + + +
Exclusive @@ -385,7 +388,7 @@ Enter Solana Recipient {/if} - {:else if !allowanceCheck} + {:else if !allowanceCheck && !hasSolanaInput} {#snippet name()} Set allowance diff --git a/src/lib/state.svelte.ts b/src/lib/state.svelte.ts index 2c92669..859f816 100644 --- a/src/lib/state.svelte.ts +++ b/src/lib/state.svelte.ts @@ -9,12 +9,14 @@ import { INPUT_SETTLER_ESCROW_LIFI, MULTICHAIN_INPUT_SETTLER_COMPACT, MULTICHAIN_INPUT_SETTLER_ESCROW, + solanaDevnetConnection, type availableAllocators, type Token, type Verifier, type WC } from "./config"; -import { getAllowance, getBalance, getCompactBalance } from "./libraries/token"; +import { getAllowance, getBalance, getCompactBalance, getSolanaBalance } from "./libraries/token"; +import solanaWallet from "./utils/solana-wallet.svelte"; import { browser } from "$app/environment"; import { initDb, db } from "./db"; import { @@ -260,6 +262,24 @@ class Store { }); }); + solanaBalances = $derived.by(() => { + this.refreshEpoch; + const account = this.solanaPublicKey || undefined; + const resolved: Partial>>> = {}; + if (!account) return resolved; + for (const token of coinList(this.mainnet)) { + if (token.chainId !== 11) continue; + if (!resolved.solanaDevnet) resolved.solanaDevnet = {}; + const key = `balance:${this.mainnet ? "mainnet" : "testnet"}:${token.chainId}:${token.address}:${account}`; + resolved.solanaDevnet[token.address] = getOrFetchRpc( + key, + () => getSolanaBalance(account, token.address, solanaDevnetConnection), + { ttlMs: 30_000 } + ); + } + return resolved; + }); + multichain = $derived([...new Set(this.inputTokens.map((i) => i.token.chainId))].length > 1); inputSettler = $derived.by(() => { @@ -275,6 +295,8 @@ class Store { recipient: string = $state(""); solanaRecipient: string = $state(""); exclusiveFor: string = $state(""); + + solanaPublicKey = $derived(solanaWallet.publicKey ?? ""); useExclusiveForQuoteRequest = $state(false); invalidateWalletReadCache(scope: "all" | "balance" | "allowance" | "compact" = "all") { diff --git a/src/lib/utils/solana-wallet.svelte.ts b/src/lib/utils/solana-wallet.svelte.ts new file mode 100644 index 0000000..d1feee8 --- /dev/null +++ b/src/lib/utils/solana-wallet.svelte.ts @@ -0,0 +1,59 @@ +import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom"; +import { SolflareWalletAdapter } from "@solana/wallet-adapter-solflare"; +import type { WalletAdapter } from "@solana/wallet-adapter-base"; + +export const AVAILABLE_WALLETS = [ + { name: "Phantom", adapter: new PhantomWalletAdapter() }, + { name: "Solflare", adapter: new SolflareWalletAdapter() } +] as const; + +class SolanaWalletStore { + #adapter = $state(null); + #connected = $state(false); + #publicKey = $state(null); + + get adapter(): WalletAdapter | null { + return this.#adapter; + } + + get connected(): boolean { + return this.#connected; + } + + /** Base58-encoded public key of the connected wallet, or null */ + get publicKey(): string | null { + return this.#publicKey; + } + + async connect(adapter: WalletAdapter): Promise { + if (this.#adapter?.connected) { + this.#adapter.off("connect"); + this.#adapter.off("disconnect"); + await this.#adapter.disconnect(); + } + this.#adapter = adapter; + adapter.on("connect", (pk) => { + this.#connected = true; + this.#publicKey = pk.toBase58(); + }); + adapter.on("disconnect", () => { + this.#connected = false; + this.#publicKey = null; + }); + await adapter.connect(); + } + + async disconnect(): Promise { + if (this.#adapter) { + this.#adapter.off("connect"); + this.#adapter.off("disconnect"); + await this.#adapter.disconnect(); + } + this.#adapter = null; + this.#connected = false; + this.#publicKey = null; + } +} + +const solanaWallet = new SolanaWalletStore(); +export default solanaWallet; From 3a9895c2fcc8a787caade92507b9ac877d6ac0ad Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Thu, 5 Mar 2026 12:49:21 +0100 Subject: [PATCH 06/14] feat: issue solana intent --- package.json | 6 +- src/lib/abi/input_settler_escrow.json | 691 ++++++++++++++++++++++++++ src/lib/libraries/intent.ts | 24 + src/lib/libraries/intentFactory.ts | 35 +- src/lib/libraries/solanaEscrowLib.ts | 153 ++++++ vite.config.ts | 12 +- 6 files changed, 908 insertions(+), 13 deletions(-) create mode 100644 src/lib/abi/input_settler_escrow.json create mode 100644 src/lib/libraries/solanaEscrowLib.ts diff --git a/package.json b/package.json index e50bbbb..a407347 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", "@playwright/test": "^1.55.0", + "@rollup/plugin-inject": "^5.0.5", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^6.1.1", "@tailwindcss/vite": "^4.0.0", @@ -46,9 +47,11 @@ "vite": "^7.1.1" }, "dependencies": { - "@lifi/intent": "0.0.3-alpha.1", + "@coral-xyz/anchor": "^0.32.1", "@electric-sql/pglite": "^0.3.15", + "@lifi/intent": "0.0.3-alpha.1", "@metamask/sdk": "^0.34.0", + "@solana/spl-token": "^0.4.14", "@solana/wallet-adapter-base": "^0.9.27", "@solana/wallet-adapter-phantom": "^0.9.28", "@solana/wallet-adapter-solflare": "^0.6.32", @@ -59,6 +62,7 @@ "axios": "^1.9.0", "base64-js": "^1.5.1", "bs58": "^6.0.0", + "buffer": "^6.0.3", "drizzle-orm": "^0.45.1", "rxjs": "^7.8.2", "viem": "~2.45.1", diff --git a/src/lib/abi/input_settler_escrow.json b/src/lib/abi/input_settler_escrow.json new file mode 100644 index 0000000..f8fb6b6 --- /dev/null +++ b/src/lib/abi/input_settler_escrow.json @@ -0,0 +1,691 @@ +{ + "address": "HyfCubUzStNcbAhW94PHPwRMqz2FTo9ox5HXxu2o6Ygq", + "metadata": { + "name": "input_settler_escrow", + "version": "0.0.0", + "spec": "0.1.0" + }, + "instructions": [ + { + "name": "finalise", + "docs": [ + "Finalise a filled order and send the order's input funds to the order's solver.", + "`order` is the order to be finalised.", + "`solve_params` are the solver parameters that filled each output (one per output). The first solver must be", + "the signer." + ], + "discriminator": [197, 63, 114, 249, 245, 72, 39, 132], + "accounts": [ + { + "name": "solver", + "writable": true, + "signer": true + }, + { + "name": "input_settler_escrow", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 105, 110, 112, 117, 116, 95, 115, 101, 116, 116, 108, 101, 114, 95, 101, 115, 99, + 114, 111, 119 + ] + } + ] + } + }, + { + "name": "user" + }, + { + "name": "destination" + }, + { + "name": "destination_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "destination" + }, + { + "kind": "const", + "value": [ + 6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206, 235, 121, 172, 28, + 180, 133, 237, 95, 91, 55, 145, 58, 140, 245, 133, 126, 255, 0, 169 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "order_context", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [111, 114, 100, 101, 114, 95, 99, 111, 110, 116, 101, 120, 116] + }, + { + "kind": "arg", + "path": "order" + } + ] + } + }, + { + "name": "order_pda_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "order_context" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "intents_protocol_program", + "address": "4SQaweUpT1LrRg1gh9sVEDL3Q4jZH3wxRi3qpz23SRpj" + }, + { + "name": "token_program" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "order", + "type": { + "defined": { + "name": "StandardOrder" + } + } + }, + { + "name": "solve_params", + "type": { + "vec": { + "defined": { + "name": "SolveParams" + } + } + } + } + ] + }, + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + "accounts": [ + { + "name": "deployer", + "writable": true, + "signer": true + }, + { + "name": "chain_id" + }, + { + "name": "input_settler_escrow", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 105, 110, 112, 117, 116, 95, 115, 101, 116, 116, 108, 101, 114, 95, 101, 115, 99, + 114, 111, 119 + ] + } + ] + } + }, + { + "name": "intents_protocol_program", + "address": "4SQaweUpT1LrRg1gh9sVEDL3Q4jZH3wxRi3qpz23SRpj" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "open", + "docs": [ + "Open the given `StandardOrder`. The order input funds will be pulled from the provided", + "user `signer` account, and will be escrowed until the order is finalised or expired." + ], + "discriminator": [228, 220, 155, 71, 199, 189, 60, 45], + "accounts": [ + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "input_settler_escrow", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 105, 110, 112, 117, 116, 95, 115, 101, 116, 116, 108, 101, 114, 95, 101, 115, 99, + 114, 111, 119 + ] + } + ] + } + }, + { + "name": "user_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "order_context", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [111, 114, 100, 101, 114, 95, 99, 111, 110, 116, 101, 120, 116] + }, + { + "kind": "arg", + "path": "order" + } + ] + } + }, + { + "name": "order_pda_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "order_context" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "token_program" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "order", + "type": { + "defined": { + "name": "StandardOrder" + } + } + } + ] + }, + { + "name": "refund", + "docs": [ + "Refund an order and send the order's input funds back to the user.", + "`order` is the order to be refunded." + ], + "discriminator": [2, 96, 183, 251, 63, 208, 46, 46], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "user" + }, + { + "name": "input_settler_escrow", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 105, 110, 112, 117, 116, 95, 115, 101, 116, 116, 108, 101, 114, 95, 101, 115, 99, + 114, 111, 119 + ] + } + ] + } + }, + { + "name": "order_context", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [111, 114, 100, 101, 114, 95, 99, 111, 110, 116, 101, 120, 116] + }, + { + "kind": "arg", + "path": "order" + } + ] + } + }, + { + "name": "order_pda_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "order_context" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "user_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "user" + }, + { + "kind": "const", + "value": [ + 6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206, 235, 121, 172, 28, + 180, 133, 237, 95, 91, 55, 145, 58, 140, 245, 133, 126, 255, 0, 169 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, 13, 131, 11, 90, 19, + 153, 218, 255, 16, 132, 4, 142, 123, 216, 219, 233, 248, 89 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "token_program" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "order", + "type": { + "defined": { + "name": "StandardOrder" + } + } + } + ] + } + ], + "accounts": [ + { + "name": "ChainId", + "discriminator": [203, 146, 201, 161, 230, 71, 157, 218] + }, + { + "name": "InputSettlerEscrowAccount", + "discriminator": [85, 112, 162, 215, 22, 13, 16, 72] + }, + { + "name": "OrderContext", + "discriminator": [240, 83, 159, 216, 26, 11, 225, 229] + } + ], + "events": [ + { + "name": "RefundedEvent", + "discriminator": [220, 3, 153, 244, 133, 189, 73, 119] + } + ], + "errors": [ + { + "code": 6000, + "name": "SolversLengthMismatch", + "msg": "Solvers length mismatch." + }, + { + "code": 6001, + "name": "FirstSolverNotInSolvers", + "msg": "First solver not in solvers." + } + ], + "types": [ + { + "name": "ChainId", + "docs": ["Type used to store the chain id of the chain."], + "type": { + "kind": "struct", + "fields": [ + { + "name": "chain_id", + "type": "u128" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "InputSettlerEscrowAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "chain_id", + "type": "u128" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "MandateInput", + "type": { + "kind": "struct", + "fields": [ + { + "name": "token", + "type": "pubkey" + }, + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "MandateOutput", + "type": { + "kind": "struct", + "fields": [ + { + "name": "oracle", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "settler", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "chain_id", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "token", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "amount", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "recipient", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "callback_data", + "type": "bytes" + }, + { + "name": "context", + "type": "bytes" + } + ] + } + }, + { + "name": "OrderContext", + "docs": [ + "The context to opened as an account after opening an order.", + "`input_token` is the token account of the input \"Mint\".", + "`user` is the user who opened the order.", + "`bump` is the bump of this account to be reused during finalisation." + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "input_token", + "type": "pubkey" + }, + { + "name": "user", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "RefundedEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "order_id", + "type": { + "array": ["u8", 32] + } + } + ] + } + }, + { + "name": "SolveParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "solver", + "type": { + "array": ["u8", 32] + } + }, + { + "name": "timestamp", + "type": "u32" + } + ] + } + }, + { + "name": "StandardOrder", + "type": { + "kind": "struct", + "fields": [ + { + "name": "user", + "type": "pubkey" + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "origin_chain_id", + "type": "u128" + }, + { + "name": "expires", + "type": "u32" + }, + { + "name": "fill_deadline", + "type": "u32" + }, + { + "name": "input_oracle", + "type": "pubkey" + }, + { + "name": "input", + "type": { + "defined": { + "name": "MandateInput" + } + } + }, + { + "name": "outputs", + "type": { + "vec": { + "defined": { + "name": "MandateOutput" + } + } + } + } + ] + } + } + ] +} diff --git a/src/lib/libraries/intent.ts b/src/lib/libraries/intent.ts index 1a6ca33..20b8570 100644 --- a/src/lib/libraries/intent.ts +++ b/src/lib/libraries/intent.ts @@ -1,4 +1,7 @@ import { encodeAbiParameters, encodePacked, hashStruct, keccak256, parseAbiParameters } from "viem"; +import type { Connection } from "@solana/web3.js"; +import type { WalletAdapter } from "@solana/wallet-adapter-base"; +import { openSolanaEscrow } from "./solanaEscrowLib"; import type { BatchCompact, CompactMandate, @@ -468,6 +471,27 @@ export class StandardOrderIntent { ]; } + /** + * @notice Opens a Solana→EVM intent by calling input_settler_escrow.open() on Solana. + * @param solanaPublicKey Base58 public key of the connected Solana wallet + * @param walletAdapter Connected Solana wallet adapter + * @param connection Solana Connection instance + * @returns transaction signature string + */ + async openSolana( + solanaPublicKey: string, + walletAdapter: WalletAdapter, + connection: Connection + ): Promise<[string]> { + const sig = await openSolanaEscrow({ + order: this.order, + solanaPublicKey, + walletAdapter, + connection + }); + return [sig]; + } + // -- Compact Helpers -- // compactClaimHash(): `0x${string}` { diff --git a/src/lib/libraries/intentFactory.ts b/src/lib/libraries/intentFactory.ts index 5b1b7a1..24a39df 100644 --- a/src/lib/libraries/intentFactory.ts +++ b/src/lib/libraries/intentFactory.ts @@ -4,8 +4,10 @@ import { INPUT_SETTLER_COMPACT_LIFI, INPUT_SETTLER_ESCROW_LIFI, MULTICHAIN_INPUT_SETTLER_ESCROW, + solanaDevnetConnection, type WC } from "$lib/config"; +import solanaWallet from "$lib/utils/solana-wallet.svelte"; import { maxUint256 } from "viem"; import type { CreateIntentOptions, @@ -18,11 +20,11 @@ import type { } from "@lifi/intent"; import type { AppCreateIntentOptions, AppTokenContext } from "$lib/appTypes"; import { ERC20_ABI } from "$lib/abi/erc20"; -import { Intent } from "@lifi/intent"; -import { IntentApi } from "@lifi/intent"; +import { Intent, IntentApi, StandardOrderIntent } from "@lifi/intent"; import { store } from "$lib/state.svelte"; import { depositAndRegisterCompact, openEscrowIntent, signIntentCompact } from "./intentExecution"; import { intentDeps } from "./coreDeps"; +import { openSolanaEscrow } from "./solanaEscrowLib"; function toCoreTokenContext(input: AppTokenContext): TokenContext { return { @@ -204,15 +206,28 @@ export class IntentFactory { const inputChain = inputTokens[0].token.chainId; if (this.preHook) await this.preHook(inputChain); - // Execute the open. - const transactionHashes = await openEscrowIntent(intent, account(), this.walletClient); - console.log({ tsh: transactionHashes }); + let transactionHashes: string[]; + + if (inputChain === 11) { + if (!solanaWallet.adapter || !solanaWallet.publicKey) { + throw new Error("Solana wallet not connected"); + } + if (!(intent instanceof StandardOrderIntent)) { + throw new Error("Solana intents must be single-chain"); + } + transactionHashes = [ + await openSolanaEscrow({ + order: intent.order, + solanaPublicKey: solanaWallet.publicKey, + walletAdapter: solanaWallet.adapter, + connection: solanaDevnetConnection + }) + ]; + } else { + transactionHashes = await openEscrowIntent(intent, account(), this.walletClient); + } - // for (const hash of transactionHashes) { - // await clients[inputChain].waitForTransactionReceipt({ - // hash: await hash - // }); - // } + console.log({ tsh: transactionHashes }); if (this.postHook) await this.postHook(); diff --git a/src/lib/libraries/solanaEscrowLib.ts b/src/lib/libraries/solanaEscrowLib.ts new file mode 100644 index 0000000..42f9b20 --- /dev/null +++ b/src/lib/libraries/solanaEscrowLib.ts @@ -0,0 +1,153 @@ +import { AnchorProvider, BN, Program, type Idl } from "@coral-xyz/anchor"; +import { Connection, PublicKey, SystemProgram } from "@solana/web3.js"; +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + getAssociatedTokenAddressSync +} from "@solana/spl-token"; +import { keccak256 } from "viem"; +import idl from "../abi/input_settler_escrow.json"; +import { SOLANA_INPUT_SETTLER_ESCROW, SOLANA_POLYMER_ORACLE } from "../config"; +import type { MandateOutput, StandardOrder } from "../../types"; + +/** Convert a 0x-prefixed hex string (32 bytes) to a number[] */ +function hexToBytes32(hex: `0x${string}`): number[] { + return Array.from(Buffer.from(hex.slice(2), "hex")); +} + +/** Convert a bigint to a 32-byte big-endian number[] */ +function bigintToBeBytes32(n: bigint): number[] { + return Array.from(Buffer.from(n.toString(16).padStart(64, "0"), "hex")); +} + +/** Recover a Solana PublicKey from a bigint (SPL mint stored as BigInt of its bytes32 hex) */ +function pubkeyFromBigInt(n: bigint): PublicKey { + return new PublicKey(Buffer.from(n.toString(16).padStart(64, "0"), "hex")); +} + +/** + * Open a Solana→EVM intent by calling input_settler_escrow.open() on Solana devnet. + * + * @param order EVM-format StandardOrder from intent.ts + * inputs[0] = [BigInt(bytes32SplMint), BigInt(amount)] + * @param solanaPublicKey Base58-encoded Solana wallet public key (becomes order.user) + * @param walletAdapter Connected Solana wallet adapter (Phantom, Solflare, …) + * @param connection Solana Connection instance + * @returns Solana transaction signature string + */ +export async function openSolanaEscrow(params: { + order: StandardOrder; + solanaPublicKey: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + walletAdapter: any; // WalletAdapter with signTransaction / signAllTransactions + connection: Connection; +}): Promise { + const { order, solanaPublicKey, walletAdapter, connection } = params; + + const userPubkey = new PublicKey(solanaPublicKey); + const inputSettlerProgramId = new PublicKey(SOLANA_INPUT_SETTLER_ESCROW); + const polymerProgramId = new PublicKey(SOLANA_POLYMER_ORACLE); + + // Wrap the wallet adapter as an Anchor-compatible wallet + const anchorWallet = { + publicKey: userPubkey, + signTransaction: (tx: unknown) => walletAdapter.signTransaction(tx), + signAllTransactions: (txs: unknown[]) => walletAdapter.signAllTransactions(txs) + }; + + const typedIdl = idl as Idl; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const provider = new AnchorProvider(connection, anchorWallet as any, { commitment: "confirmed" }); + // Program converts the IDL to camelCase internally; its coder uses camelCase field names. + // A standalone BorshCoder(rawIdl) would use snake_case names and fail to encode camelCase objects. + const program = new Program(typedIdl, provider); + + // Derive polymer oracle PDA (seed: "polymer", program: SOLANA_POLYMER_ORACLE) + const [polymerOraclePda] = PublicKey.findProgramAddressSync( + [Buffer.from("polymer")], + polymerProgramId + ); + + // Derive input settler escrow PDA (seed: "input_settler_escrow", program: SOLANA_INPUT_SETTLER_ESCROW) + const [inputSettlerEscrowPda] = PublicKey.findProgramAddressSync( + [Buffer.from("input_settler_escrow")], + inputSettlerProgramId + ); + + // Extract input token from EVM-format order: + // order.inputs[0] = [BigInt(bytes32SplMint), BigInt(amount)] + const inputMint = pubkeyFromBigInt(order.inputs[0][0]); + const inputAmount = new BN(order.inputs[0][1].toString()); + + // Build Anchor-format order. + // Field names are camelCase here; Anchor's BorshCoder maps them to the IDL's snake_case names. + const anchorOrder = { + user: userPubkey, + nonce: new BN(order.nonce.toString()), + originChainId: new BN(order.originChainId.toString()), + expires: order.expires, + fillDeadline: order.fillDeadline, + inputOracle: polymerOraclePda, + input: { token: inputMint, amount: inputAmount }, + outputs: order.outputs.map((o: MandateOutput) => ({ + oracle: hexToBytes32(o.oracle), + settler: hexToBytes32(o.settler), + chainId: bigintToBeBytes32(o.chainId), + token: hexToBytes32(o.token), + amount: bigintToBeBytes32(o.amount), + recipient: hexToBytes32(o.recipient), + callbackData: + o.callbackData === "0x" ? Buffer.alloc(0) : Buffer.from(o.callbackData.slice(2), "hex"), + context: o.context === "0x" ? Buffer.alloc(0) : Buffer.from(o.context.slice(2), "hex") + })) + }; + + // Compute orderId = keccak256(borsh(anchorOrder)) — mirrors Rust's StandardOrder::derive_id(). + // Follows example-scripts/utils/order.ts::orderIdHash(). + const valueForEncoding = { + ...anchorOrder, + outputs: anchorOrder.outputs.map((o) => ({ + ...o, + callbackData: o.callbackData ?? Buffer.alloc(0), + context: o.context ?? Buffer.alloc(0) + })) + }; + let encoded: Uint8Array; + try { + encoded = program.coder.types.encode("standardOrder", valueForEncoding); + } catch { + encoded = program.coder.types.encode("StandardOrder", valueForEncoding); + } + + const orderIdHex = keccak256(encoded); + const orderId = Buffer.from(orderIdHex.slice(2), "hex"); + + // Derive orderContext PDA (seeds: ["order_context", orderId], program: SOLANA_INPUT_SETTLER_ESCROW) + const [orderContext] = PublicKey.findProgramAddressSync( + [Buffer.from("order_context"), orderId], + inputSettlerProgramId + ); + + // ATA for the user (must already exist — user has a balance) + const userTokenAccount = getAssociatedTokenAddressSync(inputMint, userPubkey, false); + // ATA for the order PDA (created by the Anchor instruction) + const orderPdaTokenAccount = getAssociatedTokenAddressSync(inputMint, orderContext, true); + + // Call input_settler_escrow.open(order) + const signature = await program.methods + .open(anchorOrder) + .accounts({ + user: userPubkey, + inputSettlerEscrow: inputSettlerEscrowPda, + userTokenAccount, + orderContext, + orderPdaTokenAccount, + mint: inputMint, + tokenProgram: TOKEN_PROGRAM_ID, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId + }) + .rpc({ commitment: "confirmed" }); + + return signature; +} diff --git a/vite.config.ts b/vite.config.ts index 83ecf56..e21e961 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,10 +1,18 @@ import tailwindcss from "@tailwindcss/vite"; import { sveltekit } from "@sveltejs/kit/vite"; import { defineConfig } from "vite"; +import inject from "@rollup/plugin-inject"; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()], + plugins: [ + tailwindcss(), + sveltekit(), + inject({ + Buffer: ["buffer", "Buffer"] + }) + ], optimizeDeps: { - exclude: ["@electric-sql/pglite"] + exclude: ["@electric-sql/pglite"], + include: ["buffer"] } }); From bae089fbc52fbff5ffafb24db70d3c2f06311f60 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Sun, 8 Mar 2026 20:05:35 +0100 Subject: [PATCH 07/14] feat: migrate to @lifi/intent, move Solana utils to shared library - Add solanaAddressToBytes32 / isValidSolanaAddress to intent.ts/ (shared library) - Point @lifi/intent to local file: reference so latest build is used - Delete lintent/src/lib/libraries/intent.ts (duplicates @lifi/intent) - Delete lintent/src/lib/utils/convert.ts (Solana helpers now in @lifi/intent) - Fix solanaEscrowLib.ts: use dynamic imports for @coral-xyz/anchor / @solana/web3.js to avoid CJS/ESM bundling issues, import types from @lifi/intent - Fix intentFactory.ts: use openSolanaEscrow() directly, import from @lifi/intent - Fix config.ts: use numeric chainId keys for POLYMER_ORACLE, add Solana constants, add solanaDevnet to testnet chainList, fix clientsById type for non-EVM chains - Fix IssueIntent.svelte: import isValidSolanaAddress from @lifi/intent, fix hasSolanaInput typo - Fix state.svelte.ts: use chainId-based approach (no token.chain string) - Fix vite.config.ts: alias @solana/web3.js to CJS browser bundle to resolve borsh compat - Add @coral-xyz/anchor, @solana/spl-token, @solana/wallet-adapter-* to dependencies Co-Authored-By: Claude Sonnet 4.6 --- bun.lock | 283 +++++++- package.json | 2 +- src/lib/config.ts | 10 +- src/lib/libraries/intent.ts | 990 --------------------------- src/lib/libraries/intentFactory.ts | 2 +- src/lib/libraries/solanaEscrowLib.ts | 32 +- src/lib/screens/IssueIntent.svelte | 4 +- src/lib/utils/convert.ts | 75 -- vite.config.ts | 19 +- 9 files changed, 314 insertions(+), 1103 deletions(-) delete mode 100644 src/lib/libraries/intent.ts delete mode 100644 src/lib/utils/convert.ts diff --git a/bun.lock b/bun.lock index 5eec092..b4517e6 100644 --- a/bun.lock +++ b/bun.lock @@ -5,14 +5,22 @@ "": { "name": "cat-swapper", "dependencies": { + "@coral-xyz/anchor": "^0.32.1", "@electric-sql/pglite": "^0.3.15", - "@lifi/intent": "0.0.3-alpha.1", + "@lifi/intent": "file:../intent.ts", "@metamask/sdk": "^0.34.0", + "@solana/spl-token": "^0.4.14", + "@solana/wallet-adapter-base": "^0.9.27", + "@solana/wallet-adapter-phantom": "^0.9.28", + "@solana/wallet-adapter-solflare": "^0.6.32", + "@solana/web3.js": "^1.98.4", "@sveltejs/adapter-cloudflare": "^7.0.3", "@wagmi/connectors": "^7.2.1", "@wagmi/core": "^3.4.0", "axios": "^1.9.0", "base64-js": "^1.5.1", + "bs58": "^6.0.0", + "buffer": "^6.0.3", "drizzle-orm": "^0.45.1", "rxjs": "^7.8.2", "viem": "~2.45.1", @@ -22,6 +30,7 @@ "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", "@playwright/test": "^1.55.0", + "@rollup/plugin-inject": "^5.0.5", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^6.1.1", "@tailwindcss/vite": "^4.0.0", @@ -69,6 +78,12 @@ "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250807.0", "", {}, "sha512-Zbrz9egAfwmlkUaZ1tQ+19pt5eomCJ57mAviT1HCsvnSFP1MoffMbYiU/xUomuekHtx0aVO4EacZwchCgjSvmw=="], + "@coral-xyz/anchor": ["@coral-xyz/anchor@0.32.1", "", { "dependencies": { "@coral-xyz/anchor-errors": "^0.31.1", "@coral-xyz/borsh": "^0.31.1", "@noble/hashes": "^1.3.1", "@solana/web3.js": "^1.69.0", "bn.js": "^5.1.2", "bs58": "^4.0.1", "buffer-layout": "^1.2.2", "camelcase": "^6.3.0", "cross-fetch": "^3.1.5", "eventemitter3": "^4.0.7", "pako": "^2.0.3", "superstruct": "^0.15.4", "toml": "^3.0.0" } }, "sha512-zAyxFtfeje2FbMA1wzgcdVs7Hng/MijPKpRijoySPCicnvcTQs/+dnPZ/cR+LcXM9v9UYSyW81uRNYZtN5G4yg=="], + + "@coral-xyz/anchor-errors": ["@coral-xyz/anchor-errors@0.31.1", "", {}, "sha512-NhNEku4F3zzUSBtrYz84FzYWm48+9OvmT1Hhnwr6GnPQry2dsEqH/ti/7ASjjpoFTWRnPXrjAIT1qM6Isop+LQ=="], + + "@coral-xyz/borsh": ["@coral-xyz/borsh@0.31.1", "", { "dependencies": { "bn.js": "^5.1.2", "buffer-layout": "^1.2.0" }, "peerDependencies": { "@solana/web3.js": "^1.69.0" } }, "sha512-9N8AU9F0ubriKfNE3g1WF0/4dtlGXoBN/hd1PvbNBamBNwRgHxH4P+o3Zt7rSEloW1HUs6LfZEchlx9fW7POYw=="], + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], @@ -219,7 +234,7 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - "@lifi/intent": ["@lifi/intent@0.0.3-alpha.1", "", { "dependencies": { "ky": "^1.12.0", "viem": "~2.45.1" } }, "sha512-dzEcS8U5buW7nLpkMmC0kj5R7EQC7l8l1mBd9IWr6R5/vSnSF3kO9zVaNQOmrbezSOS9TROrOpGDUWc847d/Uw=="], + "@lifi/intent": ["@lifi/intent@file:../intent.ts", { "dependencies": { "bs58": "^6.0.0", "ky": "^1.12.0", "viem": "~2.45.1" }, "devDependencies": { "@types/bun": "^1.3.8", "bun": "^1.3.5", "husky": "9.1.7", "lint-staged": "16.1.0", "prettier": "3.4.2", "typescript": "^5.6.3" } }], "@metamask/json-rpc-engine": ["@metamask/json-rpc-engine@8.0.2", "", { "dependencies": { "@metamask/rpc-errors": "^6.2.1", "@metamask/safe-event-emitter": "^3.0.0", "@metamask/utils": "^8.3.0" } }, "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA=="], @@ -249,7 +264,7 @@ "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], - "@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], + "@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="], "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], @@ -259,6 +274,30 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PXgg5gqcS/rHwa1hF0JdM1y5TiyejVrMHoBmWY/DjtfYZoFTXie1RCFOkoG0b5diOOmUcuYarMpH7CSNTqwj+w=="], + + "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Nhssuh7GBpP5PiDSOl3+qnoIG7PJo+ec2oomDevnl9pRY6x6aD2gRt0JE+uf+A8Om2D6gjeHCxjEdrw5ZHE8mA=="], + + "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-w1gaTlqU0IJCmJ1X+PGHkdNU1n8Gemx5YKkjhkJIguvFINXEBB5U1KG82QsT65Tk4KyNMfbLTlmy4giAvUoKfA=="], + + "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-OUgPHfL6+PM2Q+tFZjcaycN3D7gdQdYlWnwMI31DXZKY1r4HINWk9aEz9t/rNaHg65edwNrt7dsv9TF7xK8xIA=="], + + "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-Ui5pAgM7JE9MzHokF0VglRMkbak3lTisY4Mf1AZutPACXWgKJC5aGrgnHBfkl7QS6fEeYb0juy1q4eRznRHOsw=="], + + "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-bzUgYj/PIZziB/ZesIP9HUyfvh6Vlf3od+TrbTTyVEuCSMKzDPQVW/yEbRp0tcHO3alwiEXwJDrWrHAguXlgiQ=="], + + "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-oqvMDYpX6dGJO03HgO5bXuccEsH3qbdO3MaAiAlO4CfkBPLUXz3N0DDElg5hz0L6ktdDVKbQVE5lfe+LAUISQg=="], + + "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-poVXvOShekbexHq45b4MH/mRjQKwACAC8lHp3Tz/hEDuz0/20oncqScnmKwzhBPEpqJvydXficXfBYuSim8opw=="], + + "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-/hOZ6S1VsTX6vtbhWVL9aAnOrdpuO54mAGUWpTdMz7dFG5UBZ/VUEiK0pBkq9A1rlBk0GeD/6Y4NBFl8Ha7cRA=="], + + "@oven/bun-windows-aarch64": ["@oven/bun-windows-aarch64@1.3.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-GXbz2swvN2DLw2dXZFeedMxSJtI64xQ9xp9Eg7Hjejg6mS2E4dP1xoQ2yAo2aZPi/2OBPAVaGzppI2q20XumHA=="], + + "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-qaS1In3yfC/Z/IGQriVmF8GWwKuNqiw7feTSJWaQhH5IbL6ENR+4wGNPniZSJFaM/SKUO0e/YCRdoVBvgU4C1g=="], + + "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-gh3UAHbUdDUG6fhLc1Csa4IGdtghue6U8oAIXWnUqawp6lwb3gOCRvp25IUnLF5vUHtgfMxuEUYV7YA2WxVutw=="], + "@paulmillr/qr": ["@paulmillr/qr@0.2.1", "", {}, "sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ=="], "@playwright/test": ["@playwright/test@1.58.2", "", { "dependencies": { "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" } }, "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA=="], @@ -271,6 +310,10 @@ "@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="], + "@rollup/plugin-inject": ["@rollup/plugin-inject@5.0.5", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "estree-walker": "^2.0.2", "magic-string": "^0.30.3" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.46.2", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.46.2", "", { "os": "android", "cpu": "arm64" }, "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ=="], @@ -321,6 +364,46 @@ "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], + "@solana/buffer-layout": ["@solana/buffer-layout@4.0.1", "", { "dependencies": { "buffer": "~6.0.3" } }, "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA=="], + + "@solana/buffer-layout-utils": ["@solana/buffer-layout-utils@0.2.0", "", { "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/web3.js": "^1.32.0", "bigint-buffer": "^1.1.5", "bignumber.js": "^9.0.1" } }, "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g=="], + + "@solana/codecs": ["@solana/codecs@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/codecs-data-structures": "2.0.0-rc.1", "@solana/codecs-numbers": "2.0.0-rc.1", "@solana/codecs-strings": "2.0.0-rc.1", "@solana/options": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ=="], + + "@solana/codecs-core": ["@solana/codecs-core@2.3.0", "", { "dependencies": { "@solana/errors": "2.3.0" }, "peerDependencies": { "typescript": ">=5.3.3" } }, "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw=="], + + "@solana/codecs-data-structures": ["@solana/codecs-data-structures@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/codecs-numbers": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog=="], + + "@solana/codecs-numbers": ["@solana/codecs-numbers@2.3.0", "", { "dependencies": { "@solana/codecs-core": "2.3.0", "@solana/errors": "2.3.0" }, "peerDependencies": { "typescript": ">=5.3.3" } }, "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg=="], + + "@solana/codecs-strings": ["@solana/codecs-strings@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/codecs-numbers": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "fastestsmallesttextencoderdecoder": "^1.0.22", "typescript": ">=5" } }, "sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g=="], + + "@solana/errors": ["@solana/errors@2.3.0", "", { "dependencies": { "chalk": "^5.4.1", "commander": "^14.0.0" }, "peerDependencies": { "typescript": ">=5.3.3" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ=="], + + "@solana/options": ["@solana/options@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/codecs-data-structures": "2.0.0-rc.1", "@solana/codecs-numbers": "2.0.0-rc.1", "@solana/codecs-strings": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA=="], + + "@solana/spl-token": ["@solana/spl-token@0.4.14", "", { "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/buffer-layout-utils": "^0.2.0", "@solana/spl-token-group": "^0.0.7", "@solana/spl-token-metadata": "^0.1.6", "buffer": "^6.0.3" }, "peerDependencies": { "@solana/web3.js": "^1.95.5" } }, "sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA=="], + + "@solana/spl-token-group": ["@solana/spl-token-group@0.0.7", "", { "dependencies": { "@solana/codecs": "2.0.0-rc.1" }, "peerDependencies": { "@solana/web3.js": "^1.95.3" } }, "sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug=="], + + "@solana/spl-token-metadata": ["@solana/spl-token-metadata@0.1.6", "", { "dependencies": { "@solana/codecs": "2.0.0-rc.1" }, "peerDependencies": { "@solana/web3.js": "^1.95.3" } }, "sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA=="], + + "@solana/wallet-adapter-base": ["@solana/wallet-adapter-base@0.9.27", "", { "dependencies": { "@solana/wallet-standard-features": "^1.3.0", "@wallet-standard/base": "^1.1.0", "@wallet-standard/features": "^1.1.0", "eventemitter3": "^5.0.1" }, "peerDependencies": { "@solana/web3.js": "^1.98.0" } }, "sha512-kXjeNfNFVs/NE9GPmysBRKQ/nf+foSaq3kfVSeMcO/iVgigyRmB551OjU3WyAolLG/1jeEfKLqF9fKwMCRkUqg=="], + + "@solana/wallet-adapter-phantom": ["@solana/wallet-adapter-phantom@0.9.28", "", { "dependencies": { "@solana/wallet-adapter-base": "^0.9.27" }, "peerDependencies": { "@solana/web3.js": "^1.98.0" } }, "sha512-g/hcuWwWjzo5l8I4vor9htniVhLxd/GhoVK52WSd0hy8IZ8/FBnV3u8ABVTheLqO13d0IVy+xTxoVBbDaMjLog=="], + + "@solana/wallet-adapter-solflare": ["@solana/wallet-adapter-solflare@0.6.32", "", { "dependencies": { "@solana/wallet-adapter-base": "^0.9.27", "@solana/wallet-standard-chains": "^1.1.1", "@solflare-wallet/metamask-sdk": "^1.0.3", "@solflare-wallet/sdk": "^1.4.2", "@wallet-standard/wallet": "^1.1.0" }, "peerDependencies": { "@solana/web3.js": "^1.98.0" } }, "sha512-FIqNyooif3yjPnw2gPNBZnsG6X9JYSrwCf1Oa0NN4/VxQcPjzGqvc+Tq1+js/nBOHju5roToeMFTbwNTdEOuZw=="], + + "@solana/wallet-standard-chains": ["@solana/wallet-standard-chains@1.1.1", "", { "dependencies": { "@wallet-standard/base": "^1.1.0" } }, "sha512-Us3TgL4eMVoVWhuC4UrePlYnpWN+lwteCBlhZDUhFZBJ5UMGh94mYPXno3Ho7+iHPYRtuCi/ePvPcYBqCGuBOw=="], + + "@solana/wallet-standard-features": ["@solana/wallet-standard-features@1.3.0", "", { "dependencies": { "@wallet-standard/base": "^1.1.0", "@wallet-standard/features": "^1.1.0" } }, "sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg=="], + + "@solana/web3.js": ["@solana/web3.js@1.98.4", "", { "dependencies": { "@babel/runtime": "^7.25.0", "@noble/curves": "^1.4.2", "@noble/hashes": "^1.4.0", "@solana/buffer-layout": "^4.0.1", "@solana/codecs-numbers": "^2.1.0", "agentkeepalive": "^4.5.0", "bn.js": "^5.2.1", "borsh": "^0.7.0", "bs58": "^4.0.1", "buffer": "6.0.3", "fast-stable-stringify": "^1.0.0", "jayson": "^4.1.1", "node-fetch": "^2.7.0", "rpc-websockets": "^9.0.2", "superstruct": "^2.0.2" } }, "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw=="], + + "@solflare-wallet/metamask-sdk": ["@solflare-wallet/metamask-sdk@1.0.3", "", { "dependencies": { "@solana/wallet-standard-features": "^1.1.0", "@wallet-standard/base": "^1.0.1", "bs58": "^5.0.0", "eventemitter3": "^5.0.1", "uuid": "^9.0.0" }, "peerDependencies": { "@solana/web3.js": "*" } }, "sha512-os5Px5PTMYKGS5tzOoyjDxtOtj0jZKnbI1Uwt8+Jsw1HHIA+Ib2UACCGNhQ/un2f8sIbTfLD1WuucNMOy8KZpQ=="], + + "@solflare-wallet/sdk": ["@solflare-wallet/sdk@1.4.2", "", { "dependencies": { "bs58": "^5.0.0", "eventemitter3": "^5.0.1", "uuid": "^9.0.0" }, "peerDependencies": { "@solana/web3.js": "*" } }, "sha512-jrseNWipwl9xXZgrzwZF3hhL0eIVxuEtoZOSLmuPuef7FgHjstuTtNJAeT4icA7pzdDV4hZvu54pI2r2f7SmrQ=="], + "@speed-highlight/core": ["@speed-highlight/core@1.2.7", "", {}, "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g=="], "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], @@ -335,6 +418,8 @@ "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.0", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ=="], + "@swc/helpers": ["@swc/helpers@0.5.19", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="], @@ -371,6 +456,8 @@ "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], @@ -383,6 +470,10 @@ "@types/node": ["@types/node@25.2.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ=="], + "@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="], + + "@types/ws": ["@types/ws@7.4.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.39.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/type-utils": "8.39.0", "@typescript-eslint/utils": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.39.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.39.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg=="], @@ -407,6 +498,12 @@ "@wagmi/core": ["@wagmi/core@3.4.0", "", { "dependencies": { "eventemitter3": "5.0.1", "mipd": "0.0.7", "zustand": "5.0.0" }, "peerDependencies": { "@tanstack/query-core": ">=5.0.0", "ox": ">=0.11.1", "typescript": ">=5.7.3", "viem": "2.x" }, "optionalPeers": ["@tanstack/query-core", "ox", "typescript"] }, "sha512-EU5gDsUp5t7+cuLv12/L8hfyWfCIKsBNiiBqpOqxZJxvAcAiQk4xFe2jMgaQPqApc3Omvxrk032M8AQ4N0cQeg=="], + "@wallet-standard/base": ["@wallet-standard/base@1.1.0", "", {}, "sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ=="], + + "@wallet-standard/features": ["@wallet-standard/features@1.1.0", "", { "dependencies": { "@wallet-standard/base": "^1.1.0" } }, "sha512-hiEivWNztx73s+7iLxsuD1sOJ28xtRix58W7Xnz4XzzA/pF0+aicnWgjOdA10doVDEDZdUuZCIIqG96SFNlDUg=="], + + "@wallet-standard/wallet": ["@wallet-standard/wallet@1.1.0", "", { "dependencies": { "@wallet-standard/base": "^1.1.0" } }, "sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg=="], + "abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" } }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="], "acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], @@ -415,6 +512,8 @@ "acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="], + "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], @@ -437,20 +536,40 @@ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "base-x": ["base-x@5.0.1", "", {}, "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg=="], + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + "bigint-buffer": ["bigint-buffer@1.1.5", "", { "dependencies": { "bindings": "^1.3.0" } }, "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA=="], + + "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + + "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], + "bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="], + + "borsh": ["borsh@0.7.0", "", { "dependencies": { "bn.js": "^5.2.0", "bs58": "^4.0.0", "text-encoding-utf-8": "^1.0.2" } }, "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA=="], + "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "bs58": ["bs58@6.0.0", "", { "dependencies": { "base-x": "^5.0.0" } }, "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw=="], + + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "buffer-layout": ["buffer-layout@1.2.2", "", {}, "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA=="], + "bufferutil": ["bufferutil@4.1.0", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw=="], + "bun": ["bun@1.3.10", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.10", "@oven/bun-darwin-x64": "1.3.10", "@oven/bun-darwin-x64-baseline": "1.3.10", "@oven/bun-linux-aarch64": "1.3.10", "@oven/bun-linux-aarch64-musl": "1.3.10", "@oven/bun-linux-x64": "1.3.10", "@oven/bun-linux-x64-baseline": "1.3.10", "@oven/bun-linux-x64-musl": "1.3.10", "@oven/bun-linux-x64-musl-baseline": "1.3.10", "@oven/bun-windows-aarch64": "1.3.10", "@oven/bun-windows-x64": "1.3.10", "@oven/bun-windows-x64-baseline": "1.3.10" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-S/CXaXXIyA4CMjdMkYQ4T2YMqnAn4s0ysD3mlsY4bUiOCqGlv28zck4Wd4H4kpvbekx15S9mUeLQ7Uxd0tYTLA=="], + "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], @@ -461,6 +580,8 @@ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], @@ -495,7 +616,7 @@ "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], - "cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -513,6 +634,8 @@ "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + "delay": ["delay@5.0.0", "", {}, "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw=="], + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], "detect-browser": ["detect-browser@5.3.0", "", {}, "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w=="], @@ -553,6 +676,10 @@ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + "es6-promise": ["es6-promise@4.2.8", "", {}, "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="], + + "es6-promisify": ["es6-promisify@5.0.0", "", { "dependencies": { "es6-promise": "^4.0.3" } }, "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ=="], + "esbuild": ["esbuild@0.25.8", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.8", "@esbuild/android-arm": "0.25.8", "@esbuild/android-arm64": "0.25.8", "@esbuild/android-x64": "0.25.8", "@esbuild/darwin-arm64": "0.25.8", "@esbuild/darwin-x64": "0.25.8", "@esbuild/freebsd-arm64": "0.25.8", "@esbuild/freebsd-x64": "0.25.8", "@esbuild/linux-arm": "0.25.8", "@esbuild/linux-arm64": "0.25.8", "@esbuild/linux-ia32": "0.25.8", "@esbuild/linux-loong64": "0.25.8", "@esbuild/linux-mips64el": "0.25.8", "@esbuild/linux-ppc64": "0.25.8", "@esbuild/linux-riscv64": "0.25.8", "@esbuild/linux-s390x": "0.25.8", "@esbuild/linux-x64": "0.25.8", "@esbuild/netbsd-arm64": "0.25.8", "@esbuild/netbsd-x64": "0.25.8", "@esbuild/openbsd-arm64": "0.25.8", "@esbuild/openbsd-x64": "0.25.8", "@esbuild/openharmony-arm64": "0.25.8", "@esbuild/sunos-x64": "0.25.8", "@esbuild/win32-arm64": "0.25.8", "@esbuild/win32-ia32": "0.25.8", "@esbuild/win32-x64": "0.25.8" }, "bin": "bin/esbuild" }, "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q=="], "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], @@ -581,6 +708,8 @@ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], "eth-rpc-errors": ["eth-rpc-errors@4.0.3", "", { "dependencies": { "fast-safe-stringify": "^2.0.6" } }, "sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg=="], @@ -589,7 +718,7 @@ "eventemitter2": ["eventemitter2@6.4.9", "", {}, "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg=="], - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], @@ -597,6 +726,8 @@ "extension-port-stream": ["extension-port-stream@3.0.0", "", { "dependencies": { "readable-stream": "^3.6.2 || ^4.4.2", "webextension-polyfill": ">=0.10.0 <1.0" } }, "sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw=="], + "eyes": ["eyes@0.1.8", "", {}, "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], @@ -607,12 +738,18 @@ "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], + "fast-stable-stringify": ["fast-stable-stringify@1.0.0", "", {}, "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag=="], + + "fastestsmallesttextencoderdecoder": ["fastestsmallesttextencoderdecoder@1.0.22", "", {}, "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw=="], + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], @@ -663,8 +800,12 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], @@ -701,8 +842,12 @@ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "isomorphic-ws": ["isomorphic-ws@4.0.1", "", { "peerDependencies": { "ws": "*" } }, "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="], + "isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="], + "jayson": ["jayson@4.3.0", "", { "dependencies": { "@types/connect": "^3.4.33", "@types/node": "^12.12.54", "@types/ws": "^7.4.4", "commander": "^2.20.3", "delay": "^5.0.0", "es6-promisify": "^5.0.0", "eyes": "^0.1.8", "isomorphic-ws": "^4.0.1", "json-stringify-safe": "^5.0.1", "stream-json": "^1.9.1", "uuid": "^8.3.2", "ws": "^7.5.10" }, "bin": { "jayson": "bin/jayson.js" } }, "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ=="], + "jiti": ["jiti@2.5.1", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], @@ -713,6 +858,8 @@ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -825,6 +972,8 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], @@ -897,13 +1046,15 @@ "rollup": ["rollup@4.46.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.46.2", "@rollup/rollup-android-arm64": "4.46.2", "@rollup/rollup-darwin-arm64": "4.46.2", "@rollup/rollup-darwin-x64": "4.46.2", "@rollup/rollup-freebsd-arm64": "4.46.2", "@rollup/rollup-freebsd-x64": "4.46.2", "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", "@rollup/rollup-linux-arm-musleabihf": "4.46.2", "@rollup/rollup-linux-arm64-gnu": "4.46.2", "@rollup/rollup-linux-arm64-musl": "4.46.2", "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", "@rollup/rollup-linux-ppc64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-musl": "4.46.2", "@rollup/rollup-linux-s390x-gnu": "4.46.2", "@rollup/rollup-linux-x64-gnu": "4.46.2", "@rollup/rollup-linux-x64-musl": "4.46.2", "@rollup/rollup-win32-arm64-msvc": "4.46.2", "@rollup/rollup-win32-ia32-msvc": "4.46.2", "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg=="], + "rpc-websockets": ["rpc-websockets@9.3.5", "", { "dependencies": { "@swc/helpers": "^0.5.11", "@types/uuid": "^10.0.0", "@types/ws": "^8.2.2", "buffer": "^6.0.3", "eventemitter3": "^5.0.1", "uuid": "^11.0.0", "ws": "^8.5.0" }, "optionalDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^6.0.0" } }, "sha512-4mAmr+AEhPYJ9TmDtxF3r3ZcbWy7W8kvZ4PoZYw/Xgp2J7WixjwTgiQZsoTDvch5nimmg3Ay6/0Kuh9oIvVs9A=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], - "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], @@ -939,6 +1090,10 @@ "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], + "stream-chain": ["stream-chain@2.2.5", "", {}, "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="], + + "stream-json": ["stream-json@1.9.1", "", { "dependencies": { "stream-chain": "^2.2.5" } }, "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw=="], + "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], @@ -949,6 +1104,8 @@ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "superstruct": ["superstruct@0.15.5", "", {}, "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "svelte": ["svelte@5.38.0", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-cWF1Oc2IM/QbktdK89u5lt9MdKxRtQnRKnf2tq6KOhYuhLOd2hbMuTiJ+vWMzAeMDe81AzbCgLd4GVtOJ4fDRg=="], @@ -963,10 +1120,14 @@ "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], + "text-encoding-utf-8": ["text-encoding-utf-8@1.0.2", "", {}, "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="], + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], @@ -1051,6 +1212,8 @@ "zustand": ["zustand@5.0.0", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ=="], + "@coral-xyz/anchor/bs58": ["bs58@4.0.1", "", { "dependencies": { "base-x": "^3.0.2" } }, "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw=="], + "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], @@ -1063,8 +1226,12 @@ "@metamask/rpc-errors/@metamask/utils": ["@metamask/utils@9.3.0", "", { "dependencies": { "@ethereumjs/tx": "^4.2.0", "@metamask/superstruct": "^3.1.0", "@noble/hashes": "^1.3.1", "@scure/base": "^1.1.3", "@types/debug": "^4.1.7", "debug": "^4.3.4", "pony-cause": "^2.1.10", "semver": "^7.5.4", "uuid": "^9.0.1" } }, "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g=="], + "@metamask/sdk/cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + "@metamask/sdk/debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], + "@metamask/sdk-communication-layer/cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + "@metamask/sdk-communication-layer/debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], "@metamask/utils/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], @@ -1073,11 +1240,55 @@ "@scure/bip32/@noble/curves": ["@noble/curves@1.9.6", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-GIKz/j99FRthB8icyJQA51E8Uk5hXmdyThjgQXRKiv9h0zeRlzSCLIzFw6K1LotZ3XuB7yzlf76qk7uBmTdFqA=="], + "@solana/codecs/@solana/codecs-core": ["@solana/codecs-core@2.0.0-rc.1", "", { "dependencies": { "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ=="], + + "@solana/codecs/@solana/codecs-numbers": ["@solana/codecs-numbers@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ=="], + + "@solana/codecs-data-structures/@solana/codecs-core": ["@solana/codecs-core@2.0.0-rc.1", "", { "dependencies": { "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ=="], + + "@solana/codecs-data-structures/@solana/codecs-numbers": ["@solana/codecs-numbers@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ=="], + + "@solana/codecs-data-structures/@solana/errors": ["@solana/errors@2.0.0-rc.1", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ=="], + + "@solana/codecs-strings/@solana/codecs-core": ["@solana/codecs-core@2.0.0-rc.1", "", { "dependencies": { "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ=="], + + "@solana/codecs-strings/@solana/codecs-numbers": ["@solana/codecs-numbers@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ=="], + + "@solana/codecs-strings/@solana/errors": ["@solana/errors@2.0.0-rc.1", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ=="], + + "@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/options/@solana/codecs-core": ["@solana/codecs-core@2.0.0-rc.1", "", { "dependencies": { "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ=="], + + "@solana/options/@solana/codecs-numbers": ["@solana/codecs-numbers@2.0.0-rc.1", "", { "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", "@solana/errors": "2.0.0-rc.1" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ=="], + + "@solana/options/@solana/errors": ["@solana/errors@2.0.0-rc.1", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ=="], + + "@solana/wallet-adapter-base/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "@solana/web3.js/bs58": ["bs58@4.0.1", "", { "dependencies": { "base-x": "^3.0.2" } }, "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw=="], + + "@solana/web3.js/superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="], + + "@solflare-wallet/metamask-sdk/bs58": ["bs58@5.0.0", "", { "dependencies": { "base-x": "^4.0.0" } }, "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ=="], + + "@solflare-wallet/metamask-sdk/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "@solflare-wallet/metamask-sdk/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "@solflare-wallet/sdk/bs58": ["bs58@5.0.0", "", { "dependencies": { "base-x": "^4.0.0" } }, "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ=="], + + "@solflare-wallet/sdk/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "@solflare-wallet/sdk/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "eciesjs/@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="], + "@wagmi/core/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "borsh/bs58": ["bs58@4.0.1", "", { "dependencies": { "base-x": "^3.0.2" } }, "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw=="], "ethereum-cryptography/@noble/curves": ["@noble/curves@1.4.2", "", { "dependencies": { "@noble/hashes": "1.4.0" } }, "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw=="], @@ -1089,8 +1300,16 @@ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "jayson/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], + + "jayson/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "jayson/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "lint-staged/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + "listr2/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -1103,15 +1322,27 @@ "obj-multiplex/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + "ox/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], + + "ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "postcss-load-config/lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="], "postcss-load-config/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + "rpc-websockets/@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + + "rpc-websockets/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "rpc-websockets/utf-8-validate": ["utf-8-validate@6.0.6", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA=="], + + "rpc-websockets/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "viem/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": "bin/esbuild" }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], @@ -1119,6 +1350,8 @@ "youch/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "@coral-xyz/anchor/bs58/base-x": ["base-x@3.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA=="], + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], @@ -1169,8 +1402,32 @@ "@metamask/sdk/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "@solana/codecs-data-structures/@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/codecs-data-structures/@solana/errors/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "@solana/codecs-strings/@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/codecs-strings/@solana/errors/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "@solana/codecs/@solana/codecs-core/@solana/errors": ["@solana/errors@2.0.0-rc.1", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ=="], + + "@solana/codecs/@solana/codecs-numbers/@solana/errors": ["@solana/errors@2.0.0-rc.1", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ=="], + + "@solana/options/@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/options/@solana/errors/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "@solana/web3.js/bs58/base-x": ["base-x@3.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA=="], + + "@solflare-wallet/metamask-sdk/bs58/base-x": ["base-x@4.0.1", "", {}, "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw=="], + + "@solflare-wallet/sdk/bs58/base-x": ["base-x@4.0.1", "", {}, "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "borsh/bs58/base-x": ["base-x@3.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA=="], + "ethereum-cryptography/@scure/bip32/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], "ethereum-cryptography/@scure/bip39/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], @@ -1179,6 +1436,8 @@ "log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], + "obj-multiplex/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "obj-multiplex/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], @@ -1230,5 +1489,13 @@ "wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], "wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], + + "@solana/codecs/@solana/codecs-core/@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/codecs/@solana/codecs-core/@solana/errors/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "@solana/codecs/@solana/codecs-numbers/@solana/errors/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "@solana/codecs/@solana/codecs-numbers/@solana/errors/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], } } diff --git a/package.json b/package.json index a407347..dadb86e 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dependencies": { "@coral-xyz/anchor": "^0.32.1", "@electric-sql/pglite": "^0.3.15", - "@lifi/intent": "0.0.3-alpha.1", + "@lifi/intent": "file:../intent.ts", "@metamask/sdk": "^0.34.0", "@solana/spl-token": "^0.4.14", "@solana/wallet-adapter-base": "^0.9.27", diff --git a/src/lib/config.ts b/src/lib/config.ts index 9c3ba44..5691f63 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -100,7 +100,13 @@ export const chainList = (mainnet: boolean) => { if (mainnet == true) { return ["ethereum", "base", "arbitrum", "megaeth", "katana", "polygon", "bsc"] as ChainName[]; } else - return ["sepolia", "optimismSepolia", "baseSepolia", "arbitrumSepolia", "solanaDevnet"] as ChainName[]; + return [ + "sepolia", + "optimismSepolia", + "baseSepolia", + "arbitrumSepolia", + "solanaDevnet" + ] as ChainName[]; }; export const chainIdList = (mainnet: boolean) => { @@ -530,7 +536,7 @@ export const chainById = Object.fromEntries(chainEntries) as Record< export const chainNameById = Object.fromEntries(chainNameEntries) as Record; export const clientsById = Object.fromEntries( - chains.map((name) => [chainMap[name].id, clients[name]]) + chains.map((name) => [chainMap[name].id, (clients as Record)[name]]) ) as Record; export type WC = ReturnType< diff --git a/src/lib/libraries/intent.ts b/src/lib/libraries/intent.ts deleted file mode 100644 index 20b8570..0000000 --- a/src/lib/libraries/intent.ts +++ /dev/null @@ -1,990 +0,0 @@ -import { encodeAbiParameters, encodePacked, hashStruct, keccak256, parseAbiParameters } from "viem"; -import type { Connection } from "@solana/web3.js"; -import type { WalletAdapter } from "@solana/wallet-adapter-base"; -import { openSolanaEscrow } from "./solanaEscrowLib"; -import type { - BatchCompact, - CompactMandate, - Element, - MandateOutput, - MultichainCompact, - MultichainOrder, - MultichainOrderComponent, - NoSignature, - Signature, - StandardOrder -} from "../../types"; -import { COMPACT_ABI } from "../abi/compact"; -import { - chainMap, - clients, - COIN_FILLER, - COMPACT, - getChainName, - getOracle, - SOLANA_OUTPUT_SETTLER_PDA, - INPUT_SETTLER_COMPACT_LIFI, - INPUT_SETTLER_ESCROW_LIFI, - MULTICHAIN_INPUT_SETTLER_COMPACT, - MULTICHAIN_INPUT_SETTLER_ESCROW, - type chain, - type Verifier, - type WC -} from "../config"; -import { ResetPeriod, toId } from "../utils/idLib"; -import { compact_type_hash, compactTypes } from "../utils/typedMessage"; -import { addressToBytes32, solanaAddressToBytes32 } from "../utils/convert"; -import { SETTLER_ESCROW_ABI } from "../abi/escrow"; -import type { TokenContext } from "$lib/state.svelte"; -import { MULTICHAIN_SETTLER_ESCROW_ABI } from "$lib/abi/multichain_escrow"; -import { SETTLER_COMPACT_ABI } from "$lib/abi/settlercompact"; -import { toHex } from "$lib/utils/interopableAddresses"; -import { MULTICHAIN_SETTLER_COMPACT_ABI } from "$lib/abi/multichain_compact"; - -type Lock = { - lockTag: `0x${string}`; - token: `0x${string}`; - amount: bigint; -}; - -export type EscrowLock = { - type: "escrow"; -}; - -export type CompactLock = { - type: "compact"; - resetPeriod: ResetPeriod; - allocatorId: string; -}; - -export type CreateIntentOptionsEscrow = { - recipient: string; - solanaRecipient?: string; - exclusiveFor: string; - inputTokens: TokenContext[]; - outputTokens: TokenContext[]; - verifier: Verifier; - account: () => `0x${string}`; - lock: EscrowLock; -}; - -export type CreateIntentOptionsCompact = { - recipient: string; - solanaRecipient?: string; - exclusiveFor: string; - inputTokens: TokenContext[]; - outputTokens: TokenContext[]; - verifier: Verifier; - account: () => `0x${string}`; - lock: CompactLock; -}; - -export type CreateIntentOptions = CreateIntentOptionsEscrow | CreateIntentOptionsCompact; - -function findChain(chainId: bigint) { - for (const [name, data] of Object.entries(chainMap)) { - if (BigInt(data.id) === chainId) { - return chainMap[name as chain]; - } - } - return undefined; -} - -function selectAllBut(arr: T[], index: number): T[] { - return [...arr.slice(0, index), ...arr.slice(index + 1, arr.length)]; -} - -function encodeOutputs(outputs: MandateOutput[]) { - return encodeAbiParameters( - parseAbiParameters( - "(bytes32 oracle, bytes32 settler, uint256 chainId, bytes32 token, uint256 amount, bytes32 recipient, bytes callbackData, bytes context)[]" - ), - [outputs] - ); -} - -const ONE_MINUTE = 60; -const ONE_HOUR = 60 * ONE_MINUTE; -const ONE_DAY = 24 * ONE_HOUR; - -/** - * @notice Class representing a Li.Fi Intent. Contains intent abstractions and helpers. - */ -export class Intent { - private lock: EscrowLock | CompactLock; - - // User facing order options - private user: () => `0x${string}`; - private recipient?: `0x${string}`; - private solanaRecipient?: `0x${string}`; - private inputs: TokenContext[]; - private outputs: TokenContext[]; - private verifier: Verifier; - - private exclusiveFor?: `0x${string}`; - - private _nonce?: bigint; - - private expiry = ONE_DAY; - private fillDeadline = 2 * ONE_HOUR; - - constructor(opts: CreateIntentOptionsEscrow | CreateIntentOptionsCompact) { - this.lock = opts.lock; - - this.user = opts.account; - if (opts.recipient.trim().length > 0) { - this.recipient = this.normalizeEvmRecipient(opts.recipient); - } - if (opts.solanaRecipient && opts.solanaRecipient.trim().length > 0) { - this.solanaRecipient = this.normalizeSolanaRecipient(opts.solanaRecipient); - } - this.inputs = opts.inputTokens; - this.outputs = opts.outputTokens; - this.verifier = opts.verifier; - - this.exclusiveFor = this.normalizeExclusiveFor(opts.exclusiveFor); - } - - private normalizeEvmRecipient(recipient: string): `0x${string}` { - const trimmed = recipient.trim(); - const normalized = trimmed.toLowerCase(); - if (!/^0x[0-9a-f]{40}$/.test(normalized)) { - throw new Error(`EVM recipient not formatted correctly: ${recipient}`); - } - return normalized as `0x${string}`; - } - - private normalizeSolanaRecipient(recipient: string): `0x${string}` { - return solanaAddressToBytes32(recipient.trim()); - } - - private getRecipientBytes32(chain: string): `0x${string}` { - if (chain === "solanaDevnet") { - if (!this.solanaRecipient) - throw new Error("Solana recipient is required for solanaDevnet outputs"); - return this.solanaRecipient; - } - const evmRecipient = this.recipient ?? this.user(); - return addressToBytes32(evmRecipient); - } - - private normalizeExclusiveFor(exclusiveFor: string): `0x${string}` | undefined { - const trimmed = exclusiveFor.trim(); - if (trimmed.length === 0) return undefined; - const normalized = trimmed.toLowerCase(); - if (!/^0x[0-9a-f]{40}$/.test(normalized)) { - throw new Error(`ExclusiveFor not formatted correctly ${exclusiveFor}`); - } - return normalized as `0x${string}`; - } - - numInputChains() { - const tokenChains = this.inputs.map(({ token }) => token.chain); - return [...new Set(tokenChains)].length; - } - - isMultichain() { - return this.numInputChains() > 1; - } - - isSameChain() { - // Multichain intents cannot be same chain. Normal "Output oracle" will be used. - if (this.isMultichain()) return false; - - // Only 1 input chain is used. - const inputChain = this.inputs[0].token.chain; - const outputChains = this.outputs.map((o) => o.token.chain); - const numOutputChains = [...new Set(outputChains)].length; - if (numOutputChains > 1) return false; - // Only 1 output chain is used. - const outputChain = this.outputs[0].token.chain; - return inputChain === outputChain; - } - - nonce() { - if (this._nonce) return this._nonce; - this._nonce = BigInt(Math.floor(Math.random() * 2 ** 32)); - return this._nonce; - } - - inputSettler(multichain: boolean) { - if (this.lock.type === "compact" && multichain === false) return INPUT_SETTLER_COMPACT_LIFI; - if (this.lock.type === "compact" && multichain === true) - return MULTICHAIN_INPUT_SETTLER_COMPACT; - if (this.lock.type === "escrow" && multichain === false) return INPUT_SETTLER_ESCROW_LIFI; - if (this.lock.type === "escrow" && multichain === true) return MULTICHAIN_INPUT_SETTLER_ESCROW; - - throw new Error(`Not supported | multichain: ${multichain}, type: ${this.lock.type}`); - } - - encodeOutputs(currentTime: number) { - // Get the current epoch timestamp: - currentTime; - const ONE_MINUTE = 60; - - let context: `0x${string}` = "0x"; - if (this.exclusiveFor) { - const paddedExclusiveFor: `0x${string}` = `0x${this.exclusiveFor.replace("0x", "").padStart(64, "0")}`; - context = encodePacked( - ["bytes1", "bytes32", "uint32"], - ["0xe0", paddedExclusiveFor, currentTime + ONE_MINUTE] - ); - } - - const sameChain = this.isSameChain(); - - return this.outputs.map(({ token, amount }) => { - const isSolana = token.chain === "solanaDevnet"; - const outputSettler = isSolana ? SOLANA_OUTPUT_SETTLER_PDA : COIN_FILLER; - const settlerBytes32 = isSolana - ? (outputSettler as `0x${string}`) - : addressToBytes32(outputSettler); - const outputOracle = sameChain - ? settlerBytes32 - : addressToBytes32(getOracle(this.verifier, token.chain)!); - return { - oracle: outputOracle, - settler: settlerBytes32, - chainId: BigInt(chainMap[token.chain].id), - token: addressToBytes32(token.address), - amount: amount, - recipient: this.getRecipientBytes32(token.chain), - callbackData: "0x", - context - }; - }) as MandateOutput[]; - } - - singlechain() { - if (this.isMultichain()) - throw new Error(`Not supported as single chain with ${this.numInputChains()} chains`); - - const inputChain = this.inputs[0].token.chain; - - const inputs: [bigint, bigint][] = this.inputs.map(({ token, amount }) => [ - this.lock.type === "compact" - ? toId(true, this.lock.resetPeriod, this.lock.allocatorId, token.address) - : BigInt(token.address), - amount - ]); - - const currentTime = Math.floor(Date.now() / 1000); - - const inputOracle = this.isSameChain() ? COIN_FILLER : getOracle(this.verifier, inputChain)!; - - const order: StandardOrder = { - user: this.user(), - nonce: this.nonce(), - originChainId: BigInt(chainMap[inputChain].id), - fillDeadline: currentTime + this.fillDeadline, - expires: currentTime + this.expiry, - inputOracle: inputOracle, - inputs: inputs, - outputs: this.encodeOutputs(currentTime) - }; - - return new StandardOrderIntent(this.inputSettler(false), order); - } - - multichain() { - const currentTime = Math.floor(Date.now() / 1000); - - // TODO: Fix before release. The input oracle is not the same on every chain. - const inputOracle = getOracle(this.verifier, this.inputs[0].token.chain)!; - - // Get all unique chains and then get all inputs for each chain. - const inputs: { chainId: bigint; inputs: [bigint, bigint][] }[] = [ - ...new Set(this.inputs.map(({ token }) => token.chain)) - ].map((chain) => { - const chainInputs = this.inputs.filter(({ token }) => token.chain === chain); - - return { - chainId: BigInt(chainMap[chain].id), - inputs: chainInputs.map(({ token, amount }) => [ - this.lock.type === "compact" - ? toId(true, this.lock.resetPeriod, this.lock.allocatorId, token.address) - : BigInt(token.address), - amount - ]) - }; - }); - - const order: MultichainOrder = { - user: this.user(), - nonce: this.nonce(), - fillDeadline: currentTime + this.fillDeadline, - expires: currentTime + this.expiry, - inputOracle: inputOracle, - outputs: this.encodeOutputs(currentTime), - inputs: inputs - }; - - return new MultichainOrderIntent(this.inputSettler(true), order, this.lock); - } - - order() { - if (this.isMultichain()) return this.multichain(); - return this.singlechain(); - } -} - -/// @notice Helper function that allows you to provide an order and it will correctly generate the appropriate order. -export function orderToIntent(options: { - inputSettler: `0x${string}`; - order: StandardOrder; - lock?: { type: string }; -}): StandardOrderIntent; -export function orderToIntent(options: { - inputSettler: `0x${string}`; - order: MultichainOrder; - lock?: { type: string }; -}): MultichainOrderIntent; -export function orderToIntent(options: { - inputSettler: `0x${string}`; - order: StandardOrder | MultichainOrder; - lock?: { type: string }; -}): StandardOrderIntent | MultichainOrderIntent; -export function orderToIntent(options: { - inputSettler: `0x${string}`; - order: StandardOrder | MultichainOrder; - lock?: { type: string }; -}): StandardOrderIntent | MultichainOrderIntent { - const { inputSettler, order, lock } = options; - // Use presence of originChainId to discriminate StandardOrder vs MultichainOrder - if ("originChainId" in order) { - return new StandardOrderIntent(inputSettler, order as StandardOrder); - } - return new MultichainOrderIntent(inputSettler, order as MultichainOrder, lock); -} - -export class StandardOrderIntent { - inputSettler: `0x${string}`; - order: StandardOrder; - - constructor(inputSetter: `0x${string}`, order: StandardOrder) { - this.inputSettler = inputSetter; - this.order = order; - } - - // -- Order Representations -- // - - /** - * @notice Returns for logging - */ - asOrder(): StandardOrder { - return this.order; - } - - /** - * @notice Returns the order as a StandardOrder. - * @returns Order as StandardOrder - */ - asStandardOrder(): StandardOrder { - return this.order; - } - - /** - * @notice Returns the order as a BatchCompact. - * @returns Order as BatchCompact (signed object for Compact) - */ - asBatchCompact(): BatchCompact { - const { order } = this; - const mandate: CompactMandate = { - fillDeadline: order.fillDeadline, - inputOracle: order.inputOracle, - outputs: order.outputs - }; - const commitments = order.inputs.map(([tokenId, amount]) => { - const lockTag: `0x${string}` = `0x${toHex(tokenId, 32).slice(0, 12 * 2)}`; - const token: `0x${string}` = `0x${toHex(tokenId, 32).slice(12 * 2, 32 * 2)}`; - return { - lockTag, - token, - amount - }; - }); - return { - arbiter: INPUT_SETTLER_COMPACT_LIFI, - sponsor: order.user, - nonce: order.nonce, - expires: BigInt(order.expires), - commitments, - mandate - }; - } - - inputChains(): bigint[] { - return [this.order.originChainId]; - } - - orderId(): `0x${string}` { - return keccak256( - encodePacked( - [ - "uint256", - "address", - "address", - "uint256", - "uint32", - "uint32", - "address", - "bytes32", - "bytes" - ], - [ - this.order.originChainId, - this.inputSettler, - this.order.user, - this.order.nonce, - this.order.expires, - this.order.fillDeadline, - this.order.inputOracle, - keccak256(encodePacked(["uint256[2][]"], [this.order.inputs])), - encodeOutputs(this.order.outputs) - ] - ) - ); - } - - // -- Escrow Helpers -- // - - /** - * @notice Opens an intent using the escrow input settler by depositing into it. - * @param account Account that calls open. - * @param walletClient Wallet client for sending the call to. - * @returns transactionHash for the on-chain call. - */ - async openEscrow(account: `0x${string}`, walletClient: WC): Promise<[`0x${string}`]> { - const chain = findChain(this.order.originChainId); - walletClient.switchChain({ id: Number(this.order.originChainId) }); - if (!chain) - throw new Error("Chain not found for chainId " + this.order.originChainId.toString()); - return [ - await walletClient.writeContract({ - chain, - account, - address: INPUT_SETTLER_ESCROW_LIFI, - abi: SETTLER_ESCROW_ABI, - functionName: "open", - args: [this.order] - }) - ]; - } - - /** - * @notice Opens a Solana→EVM intent by calling input_settler_escrow.open() on Solana. - * @param solanaPublicKey Base58 public key of the connected Solana wallet - * @param walletAdapter Connected Solana wallet adapter - * @param connection Solana Connection instance - * @returns transaction signature string - */ - async openSolana( - solanaPublicKey: string, - walletAdapter: WalletAdapter, - connection: Connection - ): Promise<[string]> { - const sig = await openSolanaEscrow({ - order: this.order, - solanaPublicKey, - walletAdapter, - connection - }); - return [sig]; - } - - // -- Compact Helpers -- // - - compactClaimHash(): `0x${string}` { - const claimHash = hashStruct({ - data: this.asBatchCompact(), - types: compactTypes, - primaryType: "BatchCompact" - }); - return claimHash; - } - - signCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { - const chainId = this.order.originChainId; - return walletClient.signTypedData({ - account, - domain: { - name: "The Compact", - version: "1", - chainId, - verifyingContract: COMPACT - } as const, - types: compactTypes, - primaryType: "BatchCompact", - message: this.asBatchCompact() - }); - } - - depositAndRegisterCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { - const chain = findChain(this.order.originChainId); - if (!chain) - throw new Error("Chain not found for chainId " + this.order.originChainId.toString()); - return walletClient.writeContract({ - chain, - account, - address: COMPACT, - abi: COMPACT_ABI, - functionName: "batchDepositAndRegisterMultiple", - args: [this.order.inputs, [[this.compactClaimHash(), compact_type_hash]]] - }); - } - - async finalise(options: { - sourceChain: chain; - account: `0x${string}`; - walletClient: WC; - solveParams: { timestamp: number; solver: `0x${string}` }[]; - signatures: { - sponsorSignature: Signature | NoSignature; - allocatorSignature: Signature | NoSignature; - }; - }) { - const { sourceChain, account, walletClient, solveParams, signatures } = options; - const actionChain = chainMap[sourceChain]; - if (actionChain.id !== Number(this.order.originChainId)) - throw new Error( - `Origin chain id and action ID does not match: ${this.order.originChainId}, ${actionChain.id}` - ); - - if (this.inputSettler.toLowerCase() === INPUT_SETTLER_ESCROW_LIFI.toLowerCase()) { - return await walletClient.writeContract({ - chain: actionChain, - account: account, - address: this.inputSettler, - abi: SETTLER_ESCROW_ABI, - functionName: "finalise", - args: [this.order, solveParams, addressToBytes32(account), "0x"] - }); - } else if (this.inputSettler.toLowerCase() === INPUT_SETTLER_COMPACT_LIFI.toLowerCase()) { - // Check whether or not we have a signature. - const { sponsorSignature, allocatorSignature } = signatures; - console.log({ - sponsorSignature, - allocatorSignature - }); - const combinedSignatures = encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ - sponsorSignature.payload ?? "0x", - allocatorSignature.payload - ]); - return await walletClient.writeContract({ - chain: actionChain, - account: account, - address: this.inputSettler, - abi: SETTLER_COMPACT_ABI, - functionName: "finalise", - args: [this.order, combinedSignatures, solveParams, addressToBytes32(account), "0x"] - }); - } else { - throw new Error(`Could not detect settler type ${this.inputSettler}`); - } - } -} - -export class MultichainOrderIntent { - lock?: { type: string } | EscrowLock | CompactLock; - - // Notice that this has to be the same address on every chain. - inputSettler: `0x${string}`; - order: MultichainOrder; - - constructor(inputSetter: `0x${string}`, order: MultichainOrder, lock?: { type: string }) { - this.inputSettler = inputSetter; - this.order = order; - - const isCompact = - this.inputSettler === INPUT_SETTLER_COMPACT_LIFI || - this.inputSettler === MULTICHAIN_INPUT_SETTLER_COMPACT; - - this.lock = lock ?? { type: isCompact ? "compact" : "escrow" }; - } - - selfTest() { - this.asOrder(); - this.inputChains(); - this.asComponents(); - - this.orderId(); - } - - /** - * @notice Returns for logging - */ - asOrder(): MultichainOrder { - return this.order; - } - - inputChains(): bigint[] { - return [...new Set(this.order.inputs.map((i) => i.chainId))]; - } - - orderId(): `0x${string}` { - // We need a random order components. - const components = this.asComponents(); - const computedOrderIds = components.map((c) => - this.lock?.type === "escrow" - ? MultichainOrderIntent.escrowOrderId(this.inputSettler, c.orderComponent, c.chainId) - : MultichainOrderIntent.compactOrderid(this.inputSettler, c.orderComponent, c.chainId) - ); - - const orderId = computedOrderIds[0]; - computedOrderIds.map((v) => { - if (v !== orderId) throw new Error(`Order ids are not equal ${computedOrderIds}`); - }); - if (this.lock?.type === "compact") { - const multichainCompactHash = hashStruct({ - data: this.asMultichainBatchCompact(), - types: compactTypes, - primaryType: "MultichainCompact" - }); - if (multichainCompactHash !== orderId) - throw new Error( - `MultichainCompact does not match orderId, ${multichainCompactHash} ${orderId}` - ); - } - return orderId; - } - - async orderIdCheck() { - const components = this.asComponents(); - const computedOrderId = this.orderId(); - const onChainOrderIds = await Promise.all( - components.map(async (component) => { - const onChainId = await clients[ - getChainName(component.chainId) as keyof typeof clients - ].readContract({ - address: this.inputSettler, - abi: MULTICHAIN_SETTLER_COMPACT_ABI, - functionName: "orderIdentifier", - args: [component.orderComponent] - }); - return onChainId; - }) - ); - console.log({ computedOrderId, onChainOrderIds }); - } - - static escrowOrderId( - inputSettler: `0x${string}`, - orderComponent: MultichainOrderComponent, - _: bigint - ) { - return keccak256( - encodePacked( - ["address", "address", "uint256", "uint32", "uint32", "address", "bytes32", "bytes"], - [ - inputSettler, - orderComponent.user, - orderComponent.nonce, - orderComponent.expires, - orderComponent.fillDeadline, - orderComponent.inputOracle, - MultichainOrderIntent.constructInputHash( - orderComponent.chainIdField, - orderComponent.chainIndex, - orderComponent.inputs, - orderComponent.additionalChains - ), - encodeOutputs(orderComponent.outputs) - ] - ) - ); - } - - static compactOrderid( - inputSettler: `0x${string}`, - orderComponent: MultichainOrderComponent, - chainId: bigint - ) { - const MULTICHAIN_COMPACT_TYPEHASH_WITH_WITNESS = keccak256( - encodePacked( - ["string"], - [ - "MultichainCompact(address sponsor,uint256 nonce,uint256 expires,Element[] elements)Element(address arbiter,uint256 chainId,Lock[] commitments,Mandate mandate)Lock(bytes12 lockTag,address token,uint256 amount)Mandate(uint32 fillDeadline,address inputOracle,MandateOutput[] outputs)MandateOutput(bytes32 oracle,bytes32 settler,uint256 chainId,bytes32 token,uint256 amount,bytes32 recipient,bytes callbackData,bytes context)" - ] - ) - ); - const { fillDeadline, inputOracle, outputs, inputs } = orderComponent; - const mandate: CompactMandate = { - fillDeadline, - inputOracle, - outputs - }; - const element: Element = { - arbiter: inputSettler, - chainId: chainId, - commitments: MultichainOrderIntent.inputsToLocks(inputs), - mandate - }; - - const elementHash = hashStruct({ - types: compactTypes, - primaryType: "Element", - data: element - }); - - const elementHashes = [ - ...orderComponent.additionalChains.slice(0, Number(orderComponent.chainIndex)), - elementHash, - ...orderComponent.additionalChains.slice(Number(orderComponent.chainIndex)) - ]; - - return keccak256( - encodeAbiParameters( - parseAbiParameters(["bytes32", "address", "uint256", "uint256", "bytes32"]), - [ - MULTICHAIN_COMPACT_TYPEHASH_WITH_WITNESS, - orderComponent.user, - orderComponent.nonce, - BigInt(orderComponent.expires), - keccak256(encodePacked(["bytes32[]"], [elementHashes])) - ] - ) - ); - } - - static hashInputs(chainId: bigint, inputs: [bigint, bigint][]) { - return keccak256(encodePacked(["uint256", "uint256[2][]"], [chainId, inputs])); - } - - static constructInputHash( - inputsChainId: bigint, - chainIndex: bigint, - inputs: [bigint, bigint][], - additionalChains: `0x${string}`[] - ) { - const inputHash = MultichainOrderIntent.hashInputs(inputsChainId, inputs); - const numSegments = additionalChains.length + 1; - if (numSegments <= chainIndex) - throw new Error(`ChainIndexOutOfRange(${chainIndex},${numSegments})`); - const claimStructure: `0x${string}`[] = []; - for (let i = 0; i < numSegments; ++i) { - const additionalChainsIndex = i > chainIndex ? i - 1 : i; - const inputHashElement = - chainIndex == BigInt(i) ? inputHash : additionalChains[additionalChainsIndex]; - claimStructure[i] = inputHashElement; - } - return keccak256(encodePacked(["bytes32[]"], [claimStructure])); - } - - static inputsToLocks(inputs: [bigint, bigint][]): Lock[] { - return inputs.map((input) => { - const bytes32 = toHex(input[0], 32); - return { - lockTag: `0x${bytes32.slice(0, 12 * 2)}`, - token: `0x${bytes32.slice(12 * 2, 32 * 2)}`, - amount: input[1] - }; - }); - } - - secondariesEcsrow(): { chainIdField: bigint; additionalChains: `0x${string}`[] }[] { - const inputsHash: `0x${string}`[] = this.order.inputs.map((input) => - keccak256(encodePacked(["uint256", "uint256[2][]"], [input.chainId, input.inputs])) - ); - return this.order.inputs.map((v, i) => { - return { - chainIdField: v.chainId, - additionalChains: selectAllBut(inputsHash, i) - }; - }); - } - - asCompactElements() { - const { fillDeadline, inputOracle, outputs, inputs } = this.order; - const mandate: CompactMandate = { - fillDeadline, - inputOracle, - outputs - }; - return inputs.map((inputs) => { - const element: Element = { - arbiter: this.inputSettler, - chainId: inputs.chainId, - commitments: MultichainOrderIntent.inputsToLocks(inputs.inputs), - mandate - }; - return element; - }); - } - - secondariesCompact(): { chainIdField: bigint; additionalChains: `0x${string}`[] }[] { - const { inputs } = this.order; - const elements = this.asCompactElements().map((element) => { - const hash = hashStruct({ - types: compactTypes, - primaryType: "Element", - data: element - }); - return hash; - }); - return inputs.map((_, i) => { - return { - chainIdField: inputs[0].chainId, - additionalChains: selectAllBut(elements, i) - }; - }); - } - - asComponents(): { chainId: bigint; orderComponent: MultichainOrderComponent }[] { - const { inputs, user, nonce, expires, fillDeadline, inputOracle, outputs } = this.order; - if (!this.lock) throw new Error(`No lock provided, cannot compute secondaries.`); - const secondaries = - this.lock.type == "escrow" ? this.secondariesEcsrow() : this.secondariesCompact(); - const components: { chainId: bigint; orderComponent: MultichainOrderComponent }[] = []; - for (let i = 0; i < inputs.length; ++i) { - const { chainIdField, additionalChains } = secondaries[i]; - - const orderComponent: MultichainOrderComponent = { - user: user, - nonce: nonce, - chainIdField: chainIdField, - chainIndex: BigInt(i), - expires: expires, - fillDeadline: fillDeadline, - inputOracle: inputOracle, - inputs: inputs[i].inputs, - outputs: outputs, - additionalChains: additionalChains - }; - components.push({ chainId: inputs[i].chainId, orderComponent }); - } - return components; - } - - // -- Compact Helpers -- // - - asMultichainBatchCompact(): MultichainCompact { - const { order } = this; - const mandate: CompactMandate = { - fillDeadline: order.fillDeadline, - inputOracle: order.inputOracle, - outputs: order.outputs - }; - const result = { - sponsor: order.user, - nonce: order.nonce, - expires: BigInt(order.expires), - elements: this.asCompactElements(), - mandate - }; - return result; - } - - compactClaimHash(): `0x${string}` { - const claimHash = hashStruct({ - data: this.asMultichainBatchCompact(), - types: compactTypes, - primaryType: "MultichainCompact" - }); - return claimHash; - } - - signCompact(account: `0x${string}`, walletClient: WC): Promise<`0x${string}`> { - this.selfTest(); - const chainId = this.order.inputs[0].chainId; - return walletClient.signTypedData({ - account, - domain: { - name: "The Compact", - version: "1", - chainId, - verifyingContract: COMPACT - } as const, - types: compactTypes, - primaryType: "MultichainCompact", - message: this.asMultichainBatchCompact() - }); - } - - // This code is depreciated and needs to be updated. - async openEscrow(account: `0x${string}`, walletClient: WC) { - this.selfTest(); - const components = this.asComponents(); - const results: `0x${string}`[] = []; - for (const { chainId, orderComponent } of components) { - const chain = findChain(chainId)!; - walletClient.switchChain({ id: chain.id }); - results.push( - await walletClient.writeContract({ - chain, - account, - address: this.inputSettler, - abi: MULTICHAIN_SETTLER_ESCROW_ABI, - functionName: "open", - args: [orderComponent] - }) - ); - console.log(results); - } - return results; - } - - async finalise(options: { - sourceChain: chain; - account: `0x${string}`; - walletClient: WC; - solveParams: { timestamp: number; solver: `0x${string}` }[]; - signatures: { - sponsorSignature: Signature | NoSignature; - allocatorSignature: Signature | NoSignature; - }; - }) { - this.asMultichainBatchCompact(); - const { sourceChain, account, walletClient, solveParams, signatures } = options; - const actionChain = chainMap[sourceChain]; - const inputChainIds = this.inputChains().map((v) => Number(v)); - if (!inputChainIds.includes(actionChain.id)) - throw new Error( - `Action chain must be one of input chains for finalise: ${inputChainIds}, action=${actionChain.id}` - ); - // Get all components for our chain. - const components = this.asComponents().filter((c) => Number(c.chainId) === actionChain.id); - if (components.length === 0) { - throw new Error( - `No multichain order component found for action chain ${actionChain.id} (${sourceChain}).` - ); - } - - for (const { orderComponent, chainId } of components) { - if (this.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_ESCROW.toLowerCase()) { - return await walletClient.writeContract({ - chain: actionChain, - account: account, - address: this.inputSettler, - abi: MULTICHAIN_SETTLER_ESCROW_ABI, - functionName: "finalise", - args: [orderComponent, solveParams, addressToBytes32(account), "0x"] - }); - } else if ( - this.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_COMPACT.toLowerCase() - ) { - const { sponsorSignature, allocatorSignature } = signatures; - console.log({ - orderComponent, - sponsorSignature, - allocatorSignature - }); - - const combinedSignatures = encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ - sponsorSignature.payload ?? "0x", - allocatorSignature.payload - ]); - return await walletClient.writeContract({ - chain: actionChain, - account: account, - address: this.inputSettler, - abi: MULTICHAIN_SETTLER_COMPACT_ABI, - functionName: "finalise", - args: [orderComponent, combinedSignatures, solveParams, addressToBytes32(account), "0x"] - }); - } else { - throw new Error(`Could not detect settler type ${this.inputSettler}`); - } - } - throw new Error(`Failed to finalise multichain order on chain ${sourceChain}.`); - } -} diff --git a/src/lib/libraries/intentFactory.ts b/src/lib/libraries/intentFactory.ts index 24a39df..56e34d5 100644 --- a/src/lib/libraries/intentFactory.ts +++ b/src/lib/libraries/intentFactory.ts @@ -217,7 +217,7 @@ export class IntentFactory { } transactionHashes = [ await openSolanaEscrow({ - order: intent.order, + order: intent.asOrder() as import("@lifi/intent").StandardOrder, solanaPublicKey: solanaWallet.publicKey, walletAdapter: solanaWallet.adapter, connection: solanaDevnetConnection diff --git a/src/lib/libraries/solanaEscrowLib.ts b/src/lib/libraries/solanaEscrowLib.ts index 42f9b20..6fd523c 100644 --- a/src/lib/libraries/solanaEscrowLib.ts +++ b/src/lib/libraries/solanaEscrowLib.ts @@ -1,14 +1,7 @@ -import { AnchorProvider, BN, Program, type Idl } from "@coral-xyz/anchor"; -import { Connection, PublicKey, SystemProgram } from "@solana/web3.js"; -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - getAssociatedTokenAddressSync -} from "@solana/spl-token"; import { keccak256 } from "viem"; import idl from "../abi/input_settler_escrow.json"; import { SOLANA_INPUT_SETTLER_ESCROW, SOLANA_POLYMER_ORACLE } from "../config"; -import type { MandateOutput, StandardOrder } from "../../types"; +import type { MandateOutput, StandardOrder } from "@lifi/intent"; /** Convert a 0x-prefixed hex string (32 bytes) to a number[] */ function hexToBytes32(hex: `0x${string}`): number[] { @@ -20,11 +13,6 @@ function bigintToBeBytes32(n: bigint): number[] { return Array.from(Buffer.from(n.toString(16).padStart(64, "0"), "hex")); } -/** Recover a Solana PublicKey from a bigint (SPL mint stored as BigInt of its bytes32 hex) */ -function pubkeyFromBigInt(n: bigint): PublicKey { - return new PublicKey(Buffer.from(n.toString(16).padStart(64, "0"), "hex")); -} - /** * Open a Solana→EVM intent by calling input_settler_escrow.open() on Solana devnet. * @@ -40,14 +28,26 @@ export async function openSolanaEscrow(params: { solanaPublicKey: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any walletAdapter: any; // WalletAdapter with signTransaction / signAllTransactions - connection: Connection; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + connection: any; // Connection from @solana/web3.js }): Promise { + // Dynamic imports to avoid CJS/ESM bundling issues with Rollup + const { AnchorProvider, BN, Program } = await import("@coral-xyz/anchor"); + const { PublicKey, SystemProgram } = await import("@solana/web3.js"); + const { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync } = + await import("@solana/spl-token"); + const { order, solanaPublicKey, walletAdapter, connection } = params; const userPubkey = new PublicKey(solanaPublicKey); const inputSettlerProgramId = new PublicKey(SOLANA_INPUT_SETTLER_ESCROW); const polymerProgramId = new PublicKey(SOLANA_POLYMER_ORACLE); + /** Recover a Solana PublicKey from a bigint (SPL mint stored as BigInt of its bytes32 hex) */ + function pubkeyFromBigInt(n: bigint) { + return new PublicKey(Buffer.from(n.toString(16).padStart(64, "0"), "hex")); + } + // Wrap the wallet adapter as an Anchor-compatible wallet const anchorWallet = { publicKey: userPubkey, @@ -55,7 +55,8 @@ export async function openSolanaEscrow(params: { signAllTransactions: (txs: unknown[]) => walletAdapter.signAllTransactions(txs) }; - const typedIdl = idl as Idl; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const typedIdl = idl as any; // eslint-disable-next-line @typescript-eslint/no-explicit-any const provider = new AnchorProvider(connection, anchorWallet as any, { commitment: "confirmed" }); // Program converts the IDL to camelCase internally; its coder uses camelCase field names. @@ -103,7 +104,6 @@ export async function openSolanaEscrow(params: { }; // Compute orderId = keccak256(borsh(anchorOrder)) — mirrors Rust's StandardOrder::derive_id(). - // Follows example-scripts/utils/order.ts::orderIdHash(). const valueForEncoding = { ...anchorOrder, outputs: anchorOrder.outputs.map((o) => ({ diff --git a/src/lib/screens/IssueIntent.svelte b/src/lib/screens/IssueIntent.svelte index e77f8b8..9badeb4 100644 --- a/src/lib/screens/IssueIntent.svelte +++ b/src/lib/screens/IssueIntent.svelte @@ -6,7 +6,7 @@ import SectionCard from "$lib/components/ui/SectionCard.svelte"; import { POLYMER_ALLOCATOR, formatTokenAmount, getChainName } from "$lib/config"; import { isAddress } from "viem"; - import { isValidSolanaAddress } from "$lib/utils/convert"; + import { isValidSolanaAddress } from "@lifi/intent"; import { IntentFactory, escrowApprove } from "$lib/libraries/intentFactory"; import { CompactLib } from "$lib/libraries/compactLib"; import store from "$lib/state.svelte"; @@ -388,7 +388,7 @@ Enter Solana Recipient {/if} - {:else if !allowanceCheck && !hasSolanaInput} + {:else if !allowanceCheck && !hasSolanaOutput} {#snippet name()} Set allowance diff --git a/src/lib/utils/convert.ts b/src/lib/utils/convert.ts deleted file mode 100644 index e0d1e9b..0000000 --- a/src/lib/utils/convert.ts +++ /dev/null @@ -1,75 +0,0 @@ -// --- Type conversion helpers --- // - -import { checksumAddress } from "viem"; -import bs58 from "bs58"; - -export function solanaAddressToBytes32(base58Address: string): `0x${string}` { - const decoded = bs58.decode(base58Address); - if (decoded.length !== 32) { - throw new Error(`Invalid Solana address: expected 32 bytes, got ${decoded.length}`); - } - const hex = Array.from(decoded) - .map((b) => b.toString(16).padStart(2, "0")) - .join(""); - return `0x${hex}`; -} - -export function isValidSolanaAddress(value: string): boolean { - try { - const decoded = bs58.decode(value.trim()); - return decoded.length === 32; - } catch { - return false; - } -} - -export function toBigIntWithDecimals(value: number, decimals: number): bigint { - // Convert number to string in full precision - const [intPart, decPart = ""] = value.toString().split("."); - - // Take up to `decimals` digits of the decimal part - const truncatedDec = decPart.slice(0, decimals); - - // Pad the decimal part to ensure we have exactly `decimals` digits - const paddedDec = truncatedDec.padEnd(decimals, "0"); - - // Remove leading zeros from intPart just in case - const normalizedInt = intPart.replace(/^(-?)0+(?=\d)/, "$1"); - // Combine parts - const combined = (normalizedInt + paddedDec).replace(".", ""); - - return BigInt(combined); -} - -export function addressToBytes32(address: `0x${string}`): `0x${string}` { - const raw = address.replace("0x", ""); - if (raw.length !== 40 && raw.length !== 64) { - throw new Error(`Invalid address length: ${address.length}`); - } - return `0x${raw.padStart(64, "0")}`; -} - -export function bytes32ToAddress(bytes: `0x${string}`): `0x${string}` { - if (bytes.length != 66 && bytes.length != 64) { - throw new Error(`Invalid bytes length: ${bytes.length}`); - } - return `0x${bytes.replace("0x", "").slice(24, 64)}`; -} - -export function idToToken(id: `0x${string}` | bigint): `0x${string}` { - if (typeof id === "string" && id.indexOf("0x") != 0) { - id = BigInt(id); - } - if (typeof id === "bigint") { - // Convert bigint to hex string and pad it to 64 characters. - id = `0x${id.toString(16).padStart(64, "0")}`; - } - // Remove the first 12 bytes (24 hex characters) and keep the last 20 bytes (40 hex characters). - return checksumAddress(bytes32ToAddress(id)); -} - -export function trunc(value: `0x${string}`, length: number = 6): `0x${string}...${string}` { - return `0x${value.replace("0x", "").slice(0, length)}...${value - .replace("0x", "") - .slice(-length)}`; -} diff --git a/vite.config.ts b/vite.config.ts index e21e961..590d6f3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,18 +1,21 @@ import tailwindcss from "@tailwindcss/vite"; import { sveltekit } from "@sveltejs/kit/vite"; import { defineConfig } from "vite"; -import inject from "@rollup/plugin-inject"; export default defineConfig({ - plugins: [ - tailwindcss(), - sveltekit(), - inject({ - Buffer: ["buffer", "Buffer"] - }) - ], + plugins: [tailwindcss(), sveltekit()], + resolve: { + alias: { + // Use the CJS browser bundle to avoid ESM named-import issues with borsh@0.7 + "@solana/web3.js": "@solana/web3.js/lib/index.browser.cjs.js" + } + }, optimizeDeps: { exclude: ["@electric-sql/pglite"], include: ["buffer"] + }, + define: { + // Polyfill Buffer for Solana web3.js in the browser + global: "globalThis" } }); From 15b56d25f5fd25864ea2579685fe9c022bb52543 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Mon, 9 Mar 2026 14:56:06 +0100 Subject: [PATCH 08/14] chore: support new intent.ts --- src/lib/abi/input_settler_escrow.json | 6 +-- src/lib/components/InputTokenModal.svelte | 14 ++++--- src/lib/config.ts | 14 +++---- src/lib/libraries/coreDeps.ts | 13 ++++++- src/lib/libraries/intentFactory.ts | 39 +++++++++++-------- src/lib/libraries/solanaEscrowLib.ts | 19 +++------- src/lib/screens/IntentList.svelte | 10 +++-- src/lib/screens/IssueIntent.svelte | 46 +++++++++++++++++------ src/lib/state.svelte.ts | 10 +++-- src/lib/utils/solana.ts | 19 ++++++++++ src/routes/+layout.svelte | 3 ++ src/routes/+page.svelte | 24 +++++++++--- vite.config.ts | 6 +++ 13 files changed, 155 insertions(+), 68 deletions(-) create mode 100644 src/lib/utils/solana.ts diff --git a/src/lib/abi/input_settler_escrow.json b/src/lib/abi/input_settler_escrow.json index f8fb6b6..2a6be33 100644 --- a/src/lib/abi/input_settler_escrow.json +++ b/src/lib/abi/input_settler_escrow.json @@ -1,5 +1,5 @@ { - "address": "HyfCubUzStNcbAhW94PHPwRMqz2FTo9ox5HXxu2o6Ygq", + "address": "5QngyaYhNscSebqV4DwYQhk333p5CMP8A9yyLX3pPyXC", "metadata": { "name": "input_settler_escrow", "version": "0.0.0", @@ -119,7 +119,7 @@ }, { "name": "intents_protocol_program", - "address": "4SQaweUpT1LrRg1gh9sVEDL3Q4jZH3wxRi3qpz23SRpj" + "address": "H1dVz9YXVys8c4tAihD14M5jnrUQi1MFsA65YQ92oCCz" }, { "name": "token_program" @@ -183,7 +183,7 @@ }, { "name": "intents_protocol_program", - "address": "4SQaweUpT1LrRg1gh9sVEDL3Q4jZH3wxRi3qpz23SRpj" + "address": "H1dVz9YXVys8c4tAihD14M5jnrUQi1MFsA65YQ92oCCz" }, { "name": "system_program", diff --git a/src/lib/components/InputTokenModal.svelte b/src/lib/components/InputTokenModal.svelte index 3f8a511..5381e54 100644 --- a/src/lib/components/InputTokenModal.svelte +++ b/src/lib/components/InputTokenModal.svelte @@ -1,5 +1,5 @@ diff --git a/src/lib/screens/IssueIntent.svelte b/src/lib/screens/IssueIntent.svelte index 9badeb4..cb9bcdf 100644 --- a/src/lib/screens/IssueIntent.svelte +++ b/src/lib/screens/IssueIntent.svelte @@ -4,9 +4,9 @@ import FormControl from "$lib/components/ui/FormControl.svelte"; import ScreenFrame from "$lib/components/ui/ScreenFrame.svelte"; import SectionCard from "$lib/components/ui/SectionCard.svelte"; - import { POLYMER_ALLOCATOR, formatTokenAmount, getChainName } from "$lib/config"; + import { POLYMER_ALLOCATOR, chainMap, formatTokenAmount, getChainName } from "$lib/config"; import { isAddress } from "viem"; - import { isValidSolanaAddress } from "@lifi/intent"; + import { isValidSolanaAddress, solanaAddressToBytes32 } from "$lib/utils/solana"; import { IntentFactory, escrowApprove } from "$lib/libraries/intentFactory"; import { CompactLib } from "$lib/libraries/compactLib"; import store from "$lib/state.svelte"; @@ -42,6 +42,10 @@ inputTokens: store.inputTokens, outputTokens: store.outputTokens, verifier: store.verifier, + outputRecipient: + hasSolanaOutput && isValidSolanaAddress(store.solanaRecipient) + ? solanaAddressToBytes32(store.solanaRecipient) + : undefined, lock: store.intentType === "compact" ? { @@ -99,15 +103,26 @@ let balanceCheckWallet = $state(true); $effect(() => { balanceCheckWallet = true; - if (!store.balances[store.inputTokens[0].token.chainId]) { - balanceCheckWallet = false; - return; - } for (let i = 0; i < store.inputTokens.length; ++i) { const { token, amount } = store.inputTokens[i]; - store.balances[token.chainId][token.address].then((b) => { - balanceCheckWallet = balanceCheckWallet && b >= amount; - }); + if (token.chainId === chainMap.solanaDevnet.id) { + const solBal = store.solanaBalances.solanaDevnet?.[token.address]; + if (!solBal) { + balanceCheckWallet = false; + continue; + } + solBal.then((b) => { + balanceCheckWallet = balanceCheckWallet && b >= amount; + }); + } else { + if (!store.balances[token.chainId]) { + balanceCheckWallet = false; + continue; + } + store.balances[token.chainId][token.address].then((b) => { + balanceCheckWallet = balanceCheckWallet && b >= amount; + }); + } } }); let balanceCheckCompact = $state(true); @@ -163,8 +178,15 @@ return uniqueChains.length; }); - const hasEvmOutput = $derived(store.outputTokens.some(({ token }) => token.chainId !== 11)); - const hasSolanaOutput = $derived(store.outputTokens.some(({ token }) => token.chainId === 11)); + const hasEvmOutput = $derived( + store.outputTokens.some(({ token }) => token.chainId !== chainMap.solanaDevnet.id) + ); + const hasSolanaOutput = $derived( + store.outputTokens.some(({ token }) => token.chainId === chainMap.solanaDevnet.id) + ); + const hasSolanaInput = $derived( + store.inputTokens.some(({ token }) => token.chainId === chainMap.solanaDevnet.id) + ); const evmRecipientValid = $derived( !hasEvmOutput || @@ -388,7 +410,7 @@ Enter Solana Recipient {/if} - {:else if !allowanceCheck && !hasSolanaOutput} + {:else if !allowanceCheck && !hasSolanaOutput && !hasSolanaInput} {#snippet name()} Set allowance diff --git a/src/lib/state.svelte.ts b/src/lib/state.svelte.ts index 859f816..d15cf10 100644 --- a/src/lib/state.svelte.ts +++ b/src/lib/state.svelte.ts @@ -2,6 +2,7 @@ import type { OrderContainer } from "@lifi/intent"; import type { AppTokenContext } from "./appTypes"; import { ALWAYS_OK_ALLOCATOR, + chainMap, clientsById, coinList, COMPACT, @@ -25,7 +26,7 @@ import { transactionReceipts as transactionReceiptsTable } from "./schema"; import { and, eq } from "drizzle-orm"; -import { orderToIntent } from "@lifi/intent"; +import { orderToIntent, isSolanaOriginOrder } from "@lifi/intent"; import { getOrFetchRpc, invalidateRpcPrefix } from "./libraries/rpcCache"; import { getCurrentConnection, @@ -50,6 +51,7 @@ class Store { async saveOrderToDb(order: OrderContainer) { if (!browser) return; + if (isSolanaOriginOrder(order.order)) return; if (!db) await initDb(); const orderId = orderToIntent(order).orderId(); const now = Math.floor(Date.now() / 1000); @@ -91,7 +93,9 @@ class Store { console.warn("saveOrderToDb db write failed", { orderId, error }); } } - const idx = this.orders.findIndex((o) => orderToIntent(o).orderId() === orderId); + const idx = this.orders.findIndex( + (o) => !isSolanaOriginOrder(o.order) && orderToIntent(o).orderId() === orderId + ); if (idx >= 0) this.orders[idx] = order; else this.orders.push(order); } @@ -268,7 +272,7 @@ class Store { const resolved: Partial>>> = {}; if (!account) return resolved; for (const token of coinList(this.mainnet)) { - if (token.chainId !== 11) continue; + if (token.chainId !== chainMap.solanaDevnet.id) continue; if (!resolved.solanaDevnet) resolved.solanaDevnet = {}; const key = `balance:${this.mainnet ? "mainnet" : "testnet"}:${token.chainId}:${token.address}:${account}`; resolved.solanaDevnet[token.address] = getOrFetchRpc( diff --git a/src/lib/utils/solana.ts b/src/lib/utils/solana.ts new file mode 100644 index 0000000..cc32de4 --- /dev/null +++ b/src/lib/utils/solana.ts @@ -0,0 +1,19 @@ +import { PublicKey } from "@solana/web3.js"; + +/** Convert a Base58 Solana public key to a 0x-prefixed 32-byte hex string. */ +export function solanaAddressToBytes32(base58: string): `0x${string}` { + const bytes = new PublicKey(base58).toBytes(); + return `0x${Array.from(bytes) + .map((b) => b.toString(16).padStart(2, "0")) + .join("")}`; +} + +/** Returns true if the string is a valid Base58 Solana public key. */ +export function isValidSolanaAddress(address: string): boolean { + try { + new PublicKey(address); + return true; + } catch { + return false; + } +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 2458f08..37ff705 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,4 +1,7 @@ diff --git a/src/lib/state.svelte.ts b/src/lib/state.svelte.ts index d15cf10..5877a1d 100644 --- a/src/lib/state.svelte.ts +++ b/src/lib/state.svelte.ts @@ -26,7 +26,7 @@ import { transactionReceipts as transactionReceiptsTable } from "./schema"; import { and, eq } from "drizzle-orm"; -import { orderToIntent, isSolanaOriginOrder } from "@lifi/intent"; +import { orderToIntent } from "@lifi/intent"; import { getOrFetchRpc, invalidateRpcPrefix } from "./libraries/rpcCache"; import { getCurrentConnection, @@ -51,7 +51,6 @@ class Store { async saveOrderToDb(order: OrderContainer) { if (!browser) return; - if (isSolanaOriginOrder(order.order)) return; if (!db) await initDb(); const orderId = orderToIntent(order).orderId(); const now = Math.floor(Date.now() / 1000); @@ -93,9 +92,7 @@ class Store { console.warn("saveOrderToDb db write failed", { orderId, error }); } } - const idx = this.orders.findIndex( - (o) => !isSolanaOriginOrder(o.order) && orderToIntent(o).orderId() === orderId - ); + const idx = this.orders.findIndex((o) => orderToIntent(o).orderId() === orderId); if (idx >= 0) this.orders[idx] = order; else this.orders.push(order); } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 9922b9a..2b98745 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -13,7 +13,7 @@ import ConnectWallet from "$lib/screens/ConnectWallet.svelte"; import FlowStepTracker from "$lib/components/ui/FlowStepTracker.svelte"; import store from "$lib/state.svelte"; - import { orderToIntent, isSolanaOriginOrder } from "@lifi/intent"; + import { orderToIntent } from "@lifi/intent"; // Fix bigint so we can json serialize it: (BigInt.prototype as any).toJSON = function () { @@ -66,14 +66,9 @@ } as NoSignature); const orderContainer = { ...order, allocatorSignature, sponsorSignature }; - // Skip Solana-origin orders — they have 32-byte users and cannot be processed here - if (isSolanaOriginOrder(orderContainer.order)) return; - // Deduplicate: only add if not already present const orderId = orderToIntent(orderContainer).orderId(); - const alreadyExists = store.orders - .filter((o) => !isSolanaOriginOrder(o.order)) - .some((o) => orderToIntent(o).orderId() === orderId); + const alreadyExists = store.orders.some((o) => orderToIntent(o).orderId() === orderId); if (alreadyExists) return; store.orders.push(orderContainer); @@ -105,27 +100,18 @@ let scrollStepProgress = $state(0); async function importOrderById(orderId: `0x${string}`): Promise<"inserted" | "updated"> { const importedOrder = await intentApi.getOrderByOnChainOrderId(orderId); - if (isSolanaOriginOrder(importedOrder.order)) { - throw new Error("Solana-origin orders cannot be imported into the intent list."); - } const importedOrderId = orderToIntent(importedOrder).orderId(); const existingIndex = store.orders.findIndex( - (o) => !isSolanaOriginOrder(o.order) && orderToIntent(o).orderId() === importedOrderId + (o) => orderToIntent(o).orderId() === importedOrderId ); await store.saveOrderToDb(importedOrder); selectedOrder = - store.orders.find( - (o) => !isSolanaOriginOrder(o.order) && orderToIntent(o).orderId() === importedOrderId - ) ?? importedOrder; + store.orders.find((o) => orderToIntent(o).orderId() === importedOrderId) ?? importedOrder; return existingIndex >= 0 ? "updated" : "inserted"; } async function deleteOrderById(orderId: `0x${string}`): Promise { await store.deleteOrderFromDb(orderId); - if ( - selectedOrder && - !isSolanaOriginOrder(selectedOrder.order) && - orderToIntent(selectedOrder).orderId() === orderId - ) { + if (selectedOrder && orderToIntent(selectedOrder).orderId() === orderId) { selectedOrder = undefined; } } From ee21d8525c40364b678b4c7eae27426bfd6c6c32 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Wed, 11 Mar 2026 11:34:45 +0100 Subject: [PATCH 10/14] fix: follows new changes in intent.ts --- src/lib/config.ts | 2 ++ src/lib/db.ts | 2 +- src/lib/libraries/coreDeps.ts | 9 ++--- src/lib/libraries/flowProgress.ts | 7 +++- src/lib/libraries/intentFactory.ts | 55 +++++++++++++++++++++--------- src/lib/libraries/intentList.ts | 22 +++++++++--- src/lib/libraries/solver.ts | 4 +-- src/lib/screens/Finalise.svelte | 8 ++++- 8 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/lib/config.ts b/src/lib/config.ts index 993906e..6ea2fe3 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -388,6 +388,8 @@ export function getCoin( // check chain first. if (token.chainId === chainId) { if (name === undefined) { + // Exact match first (handles full bytes32 Solana token addresses) + if (address?.toLowerCase() === token.address.toLowerCase()) return token; if (concatedAddress?.toLowerCase() === token.address.toLowerCase()) return token; } if (name?.toLowerCase() === token.name.toLowerCase()) return token; diff --git a/src/lib/db.ts b/src/lib/db.ts index 4cbcba7..8491b8e 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -23,7 +23,7 @@ export async function initDb() { initDbPromise = (async () => { // Open a PGLite database; this will persist to IndexedDB in the browser - const pglite = new PGlite("idb://orders"); + const pglite = new PGlite("idb://orders-v2"); // Create a Drizzle instance over the opened SQLite-compatible database db = drizzle(pglite); diff --git a/src/lib/libraries/coreDeps.ts b/src/lib/libraries/coreDeps.ts index 787467d..8ef27bf 100644 --- a/src/lib/libraries/coreDeps.ts +++ b/src/lib/libraries/coreDeps.ts @@ -7,7 +7,7 @@ import { SOLANA_OUTPUT_SETTLER_PDA, WORMHOLE_ORACLE } from "$lib/config"; -import type { IntentDeps, OrderContainerValidationDeps, SolanaIntentDeps } from "@lifi/intent"; +import type { IntentDeps, OrderContainerValidationDeps } from "@lifi/intent"; function isNonZeroAddress(value: string | undefined): value is `0x${string}` { return !!value && value.toLowerCase() !== "0x0000000000000000000000000000000000000000"; @@ -29,11 +29,6 @@ export const intentDeps: IntentDeps = { } }; -export const solanaDeps: SolanaIntentDeps = { - inputOracle: POLYMER_ORACLE[chainMap.solanaDevnet.id]!, - getOracle: intentDeps.getOracle -}; - export const orderValidationDeps: OrderContainerValidationDeps = { inputSettlers: [INPUT_SETTLER_COMPACT_LIFI, MULTICHAIN_INPUT_SETTLER_COMPACT], allowedInputOracles({ chainId, sameChainFill }) { @@ -60,6 +55,6 @@ export const orderValidationDeps: OrderContainerValidationDeps = { return allowed; }, allowedOutputSettlers() { - return [COIN_FILLER]; + return [COIN_FILLER, SOLANA_OUTPUT_SETTLER_PDA]; } }; diff --git a/src/lib/libraries/flowProgress.ts b/src/lib/libraries/flowProgress.ts index 510e33f..a0a6f71 100644 --- a/src/lib/libraries/flowProgress.ts +++ b/src/lib/libraries/flowProgress.ts @@ -154,7 +154,12 @@ async function isInputChainFinalised(chainId: bigint, container: OrderContainer) inputSettler === INPUT_SETTLER_COMPACT_LIFI || inputSettler === MULTICHAIN_INPUT_SETTLER_COMPACT ) { - const flattenedInputs = "originChainId" in order ? order.inputs : order.inputs[0]?.inputs; + const flattenedInputs = + "originChainId" in order && "inputs" in order + ? order.inputs + : "inputs" in order + ? order.inputs[0]?.inputs + : []; if (!flattenedInputs || flattenedInputs.length === 0) return false; return getOrFetchRpc( diff --git a/src/lib/libraries/intentFactory.ts b/src/lib/libraries/intentFactory.ts index a70b0ec..f68420d 100644 --- a/src/lib/libraries/intentFactory.ts +++ b/src/lib/libraries/intentFactory.ts @@ -18,14 +18,21 @@ import type { NoSignature, OrderContainer, Signature, - StandardOrder + StandardOrder, + SolanaStandardOrder } from "@lifi/intent"; import type { AppCreateIntentOptions, AppTokenContext } from "$lib/appTypes"; import { ERC20_ABI } from "$lib/abi/erc20"; -import { Intent, IntentApi, SolanaIntent, solanaOrderToStandardOrder } from "@lifi/intent"; +import { + Intent, + IntentApi, + SolanaStandardOrderIntent, + StandardOrderIntent, + MultichainOrderIntent +} from "@lifi/intent"; import { store } from "$lib/state.svelte"; import { depositAndRegisterCompact, openEscrowIntent, signIntentCompact } from "./intentExecution"; -import { intentDeps, solanaDeps } from "./coreDeps"; +import { intentDeps } from "./coreDeps"; import { solanaAddressToBytes32 } from "$lib/utils/solana"; import { openSolanaEscrow } from "./solanaEscrowLib"; @@ -103,7 +110,7 @@ export class IntentFactory { } private saveOrder(options: { - order: StandardOrder | MultichainOrder; + order: StandardOrder | SolanaStandardOrder | MultichainOrder; inputSettler: `0x${string}`; sponsorSignature?: Signature | NoSignature; allocatorSignature?: Signature | NoSignature; @@ -131,7 +138,9 @@ export class IntentFactory { const { account, inputTokens } = opts; const inputChain = inputTokens[0].token.chainId; if (this.preHook) await this.preHook(inputChain); - const intent = new Intent(toCoreCreateIntentOptions(opts), intentDeps).order(); + const intent = new Intent(toCoreCreateIntentOptions(opts), intentDeps).order() as + | StandardOrderIntent + | MultichainOrderIntent; const sponsorSignature = await signIntentCompact(intent, account(), this.walletClient); @@ -169,7 +178,10 @@ export class IntentFactory { compactDepositAndRegister(opts: AppCreateIntentOptions) { return async () => { const { inputTokens, account } = opts; - const intent = new Intent(toCoreCreateIntentOptions(opts), intentDeps).singlechain(); + const intent = new Intent( + toCoreCreateIntentOptions(opts), + intentDeps + ).singlechain() as StandardOrderIntent; if (this.preHook) await this.preHook(inputTokens[0].token.chainId); @@ -212,31 +224,42 @@ export class IntentFactory { if (!solanaWallet.adapter || !solanaWallet.publicKey) { throw new Error("Solana wallet not connected"); } - const solanaOrderIntent = new SolanaIntent( + // outputRecipient: Solana recipient for Solana outputs, EVM wallet for EVM outputs + const outputRecipient = opts.outputRecipient ?? account(); + const solanaOrderIntent = new Intent( { - account: solanaAddressToBytes32(solanaWallet.publicKey), - inputToken: toCoreTokenContext(inputTokens[0]), + exclusiveFor: opts.exclusiveFor, + inputTokens: [toCoreTokenContext(inputTokens[0])], outputTokens: outputTokens.map(toCoreTokenContext), verifier: opts.verifier, - exclusiveFor: opts.exclusiveFor - }, - solanaDeps - ).order(); + account: solanaAddressToBytes32(solanaWallet.publicKey), + outputRecipient, + lock: { type: "solanaEscrow" } + } as any, // CreateIntentOptions doesn't expose solanaEscrow lock type + intentDeps + ).singlechain() as SolanaStandardOrderIntent; + // fillDeadline must be strictly < expires (Solana program requirement) + const solanaOrder = { + ...solanaOrderIntent.asOrder(), + fillDeadline: solanaOrderIntent.asOrder().expires - 1 + }; transactionHashes = [ await openSolanaEscrow({ - order: solanaOrderIntent.asOrder(), + order: solanaOrder, solanaPublicKey: solanaWallet.publicKey, walletAdapter: solanaWallet.adapter, connection: solanaDevnetConnection }) ]; this.saveOrder({ - order: solanaOrderToStandardOrder(solanaOrderIntent.asOrder()), + order: solanaOrder, inputSettler: solanaAddressToBytes32(SOLANA_INPUT_SETTLER_ESCROW) }); } else { if (this.preHook) await this.preHook(inputChain); - const intent = new Intent(toCoreCreateIntentOptions(opts), intentDeps).order(); + const intent = new Intent(toCoreCreateIntentOptions(opts), intentDeps).order() as + | StandardOrderIntent + | MultichainOrderIntent; transactionHashes = await openEscrowIntent(intent, account(), this.walletClient); this.saveOrder({ order: intent.asOrder(), diff --git a/src/lib/libraries/intentList.ts b/src/lib/libraries/intentList.ts index 4689d51..2a4d46b 100644 --- a/src/lib/libraries/intentList.ts +++ b/src/lib/libraries/intentList.ts @@ -9,7 +9,12 @@ import { } from "../config"; import { orderToIntent } from "@lifi/intent"; import { bytes32ToAddress, idToToken } from "@lifi/intent"; -import type { OrderContainer, StandardOrder, MultichainOrder } from "@lifi/intent"; +import type { + OrderContainer, + StandardOrder, + SolanaStandardOrder, + MultichainOrder +} from "@lifi/intent"; import { validateOrderContainerWithReason } from "@lifi/intent"; import { orderValidationDeps } from "./coreDeps"; @@ -95,8 +100,17 @@ function summarizeOutput(chainId: bigint, token: `0x${string}`, amount: bigint): return `${amountText} ${coin.name.toUpperCase()} on ${chainName}`; } -function getInputs(order: StandardOrder | MultichainOrder) { +function getInputs(order: StandardOrder | SolanaStandardOrder | MultichainOrder) { if ("originChainId" in order) { + if ("input" in order) { + // SolanaStandardOrder — single input with bytes32 token address + return [ + { + key: `s-0-${order.input.token}`, + text: summarizeOutput(order.originChainId, order.input.token, order.input.amount) + } + ]; + } return order.inputs.map((input, index) => ({ key: `s-${index}-${input[0].toString()}`, text: summarizeInput(order.originChainId, input[0], input[1]) @@ -109,14 +123,14 @@ function getInputs(order: StandardOrder | MultichainOrder) { })); } -function getOutputs(order: StandardOrder | MultichainOrder) { +function getOutputs(order: StandardOrder | SolanaStandardOrder | MultichainOrder) { return order.outputs.map((output, index) => ({ key: `o-${index}-${output.token}`, text: summarizeOutput(output.chainId, output.token, output.amount) })); } -function getChainScope(order: StandardOrder | MultichainOrder): ChainScope { +function getChainScope(order: StandardOrder | SolanaStandardOrder | MultichainOrder): ChainScope { if (!("originChainId" in order)) return "multichain"; const isSameChain = order.outputs.every((output) => output.chainId === order.originChainId); return isSameChain ? "samechain" : "singlechain"; diff --git a/src/lib/libraries/solver.ts b/src/lib/libraries/solver.ts index 674ce29..d371b19 100644 --- a/src/lib/libraries/solver.ts +++ b/src/lib/libraries/solver.ts @@ -6,7 +6,7 @@ import axios from "axios"; import { POLYMER_ORACLE_ABI } from "$lib/abi/polymeroracle"; import { COIN_FILLER_ABI } from "$lib/abi/outputsettler"; import { ERC20_ABI } from "$lib/abi/erc20"; -import { orderToIntent } from "@lifi/intent"; +import { orderToIntent, StandardOrderIntent, MultichainOrderIntent } from "@lifi/intent"; import { compactTypes } from "@lifi/intent"; import store from "$lib/state.svelte"; import { finaliseIntent } from "./intentExecution"; @@ -313,7 +313,7 @@ export class Solver { const intent = orderToIntent({ inputSettler, order - }); + }) as StandardOrderIntent | MultichainOrderIntent; if (fillTransactionHashes.length !== order.outputs.length) { throw new Error( `Fill transaction hash count (${fillTransactionHashes.length}) does not match output count (${order.outputs.length}).` diff --git a/src/lib/screens/Finalise.svelte b/src/lib/screens/Finalise.svelte index 5dcf169..d8e2e81 100644 --- a/src/lib/screens/Finalise.svelte +++ b/src/lib/screens/Finalise.svelte @@ -45,6 +45,7 @@ const getInputsForChain = (container: OrderContainer, inputChain: bigint): [bigint, bigint][] => { const { order } = container; if ("originChainId" in order) { + if (!("inputs" in order)) return []; // SolanaStandardOrder — no [bigint, bigint][] inputs return order.originChainId === inputChain ? order.inputs : []; } return order.inputs.find((chainInput) => chainInput.chainId === inputChain)?.inputs ?? []; @@ -109,7 +110,12 @@ inputSettler === MULTICHAIN_INPUT_SETTLER_COMPACT ) { // Check claim status - const flattenedInputs = "originChainId" in order ? order.inputs : order.inputs[0]?.inputs; + const flattenedInputs = + "originChainId" in order && "inputs" in order + ? order.inputs + : "inputs" in order + ? order.inputs[0]?.inputs + : []; if (!flattenedInputs || flattenedInputs.length === 0) return false; const [token, allocator, resetPeriod, scope] = await inputChainClient.readContract({ From 7444d569c7829327ea4deeade6e3f2ce5270e879 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Fri, 13 Mar 2026 19:26:26 +0100 Subject: [PATCH 11/14] fix: replace solanaEscrow lock with escrow+chain:solana, add chain:evm to compact lock EscrowLock and CompactLock in @lifi/intent now require an explicit `chain` field. Replace the removed `solanaEscrow` lock type with `{ type: "escrow", chain: "solana" }` and add `chain: "evm"` to all EVM escrow/compact lock objects. Co-Authored-By: Claude Sonnet 4.6 --- src/lib/libraries/intentFactory.ts | 8 +++++--- src/lib/screens/IssueIntent.svelte | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/libraries/intentFactory.ts b/src/lib/libraries/intentFactory.ts index f68420d..07054a0 100644 --- a/src/lib/libraries/intentFactory.ts +++ b/src/lib/libraries/intentFactory.ts @@ -59,6 +59,7 @@ function toCoreCreateIntentOptions(opts: AppCreateIntentOptions): CreateIntentOp account, lock: { type: "compact", + chain: "evm", resetPeriod: opts.lock.resetPeriod, allocatorId: opts.lock.allocatorId } @@ -72,7 +73,8 @@ function toCoreCreateIntentOptions(opts: AppCreateIntentOptions): CreateIntentOp verifier: opts.verifier, account, lock: { - type: "escrow" + type: "escrow", + chain: "evm" } }; } @@ -234,8 +236,8 @@ export class IntentFactory { verifier: opts.verifier, account: solanaAddressToBytes32(solanaWallet.publicKey), outputRecipient, - lock: { type: "solanaEscrow" } - } as any, // CreateIntentOptions doesn't expose solanaEscrow lock type + lock: { type: "escrow", chain: "solana" } + }, intentDeps ).singlechain() as SolanaStandardOrderIntent; // fillDeadline must be strictly < expires (Solana program requirement) diff --git a/src/lib/screens/IssueIntent.svelte b/src/lib/screens/IssueIntent.svelte index cb9bcdf..25d0302 100644 --- a/src/lib/screens/IssueIntent.svelte +++ b/src/lib/screens/IssueIntent.svelte @@ -50,10 +50,11 @@ store.intentType === "compact" ? { type: "compact", + chain: "evm", allocatorId: store.allocatorId, resetPeriod: ResetPeriod.OneDay } - : { type: "escrow" }, + : { type: "escrow", chain: "evm" }, account }) ); From a1feb389b94d951cfcf13ebc0e0a282cd6018029 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Fri, 13 Mar 2026 19:50:05 +0100 Subject: [PATCH 12/14] feat: add Solana mainnet chain with structured program ID records Introduces solanaMainnet (chain id 1151111081099710) alongside the existing solanaDevnet. Replaces flat SOLANA_* constants with SOLANA_PROGRAMS and SOLANA_PDAS records keyed by devnet/mainnet; flat re-exports preserved for backward compatibility. Mainnet program IDs and PDAs are TODO placeholders. Co-Authored-By: Claude Sonnet 4.6 --- src/lib/config.ts | 104 +++++++++++++++++++++++++++++----- src/lib/libraries/coreDeps.ts | 7 ++- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/src/lib/config.ts b/src/lib/config.ts index 6ea2fe3..33263da 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -42,15 +42,60 @@ const solanaDevnet = defineChain({ }); export const solanaDevnetConnection = new Connection("https://api.devnet.solana.com", "confirmed"); -// catalyst-intent-svm program IDs (devnet) — from Anchor.toml -export const SOLANA_INTENTS_PROTOCOL = "H1dVz9YXVys8c4tAihD14M5jnrUQi1MFsA65YQ92oCCz" as const; -export const SOLANA_OUTPUT_SETTLER_SIMPLE = "58CsNaufL383JL7J1jafGW4eWgeQFX5vSZssjsk4WKXd" as const; -export const SOLANA_INPUT_SETTLER_ESCROW = "5QngyaYhNscSebqV4DwYQhk333p5CMP8A9yyLX3pPyXC" as const; -export const SOLANA_POLYMER_ORACLE = "C2rAFLS6xQ78t18rK5s9madY9fztbhTaHwShgYtzonk7" as const; - -// PDA(seed: "output_settler_simple") of the SOLANA_OUTPUT_SETTLER_SIMPLE program -export const SOLANA_OUTPUT_SETTLER_PDA = - "0xabb04f05c412a4892f8c93efa4eda9f360ba8b5c8342bed51207c7a4fdd036d6" as const; +const solanaMainnet = defineChain({ + id: 1151111081099710, + name: "Solana", + nativeCurrency: { name: "SOL", symbol: "SOL", decimals: 9 }, + rpcUrls: { + default: { http: ["https://api.mainnet-beta.solana.com"] } + } +}); +export const solanaMainnetConnection = new Connection( + "https://api.mainnet-beta.solana.com", + "confirmed" +); + +// catalyst-intent-svm program IDs, keyed by network +export const SOLANA_PROGRAMS = { + devnet: { + // from Anchor.toml + INTENTS_PROTOCOL: "H1dVz9YXVys8c4tAihD14M5jnrUQi1MFsA65YQ92oCCz", + OUTPUT_SETTLER_SIMPLE: "58CsNaufL383JL7J1jafGW4eWgeQFX5vSZssjsk4WKXd", + INPUT_SETTLER_ESCROW: "5QngyaYhNscSebqV4DwYQhk333p5CMP8A9yyLX3pPyXC", + POLYMER_ORACLE: "C2rAFLS6xQ78t18rK5s9madY9fztbhTaHwShgYtzonk7" + }, + mainnet: { + // TODO: fill in mainnet program IDs once deployed + INTENTS_PROTOCOL: "TODO_MAINNET_INTENTS_PROTOCOL", + OUTPUT_SETTLER_SIMPLE: "TODO_MAINNET_OUTPUT_SETTLER_SIMPLE", + INPUT_SETTLER_ESCROW: "TODO_MAINNET_INPUT_SETTLER_ESCROW", + POLYMER_ORACLE: "TODO_MAINNET_POLYMER_ORACLE" + } +} as const; + +// Derived PDAs, keyed by network +export const SOLANA_PDAS = { + devnet: { + // PDA(seed: "output_settler_simple", program: SOLANA_PROGRAMS.devnet.OUTPUT_SETTLER_SIMPLE) + OUTPUT_SETTLER: + "0xabb04f05c412a4892f8c93efa4eda9f360ba8b5c8342bed51207c7a4fdd036d6" as `0x${string}`, + // PDA(seed: "polymer", program: SOLANA_PROGRAMS.devnet.POLYMER_ORACLE) + POLYMER_ORACLE: + "0xe48a6f95df84c28a030f60ba5b74e4a02922a4a5724c9633109f089b2287edfc" as `0x${string}` + }, + mainnet: { + // TODO: derive PDAs from mainnet program IDs once deployed + OUTPUT_SETTLER: BYTES32_ZERO, + POLYMER_ORACLE: BYTES32_ZERO + } +} as const; + +// Flat re-exports for backward compatibility +export const SOLANA_INTENTS_PROTOCOL = SOLANA_PROGRAMS.devnet.INTENTS_PROTOCOL; +export const SOLANA_OUTPUT_SETTLER_SIMPLE = SOLANA_PROGRAMS.devnet.OUTPUT_SETTLER_SIMPLE; +export const SOLANA_INPUT_SETTLER_ESCROW = SOLANA_PROGRAMS.devnet.INPUT_SETTLER_ESCROW; +export const SOLANA_POLYMER_ORACLE = SOLANA_PROGRAMS.devnet.POLYMER_ORACLE; +export const SOLANA_OUTPUT_SETTLER_PDA = SOLANA_PDAS.devnet.OUTPUT_SETTLER; // --- Oracles --- // export const WORMHOLE_ORACLE: Partial> = { [ethereum.id]: "0x0000000000000000000000000000000000000000", @@ -70,8 +115,8 @@ export const POLYMER_ORACLE: Partial> = { [baseSepolia.id]: "0x00d5b500ECa100F7cdeDC800eC631Aca00BaAC00", [arbitrumSepolia.id]: "0x00d5b500ECa100F7cdeDC800eC631Aca00BaAC00", [optimismSepolia.id]: "0x00d5b500ECa100F7cdeDC800eC631Aca00BaAC00", - // PDA(seed: "polymer") of the SOLANA_POLYMER_ORACLE program - [solanaDevnet.id]: "0xe48a6f95df84c28a030f60ba5b74e4a02922a4a5724c9633109f089b2287edfc" + [solanaDevnet.id]: SOLANA_PDAS.devnet.POLYMER_ORACLE, + [solanaMainnet.id]: SOLANA_PDAS.mainnet.POLYMER_ORACLE }; export type availableAllocators = typeof ALWAYS_OK_ALLOCATOR | typeof POLYMER_ALLOCATOR; @@ -91,14 +136,24 @@ export const chainMap = { megaeth, bsc, polygon, - solanaDevnet + solanaDevnet, + solanaMainnet } as const; type ChainName = keyof typeof chainMap; export type chain = ChainName; export const chains = Object.keys(chainMap) as ChainName[]; export const chainList = (mainnet: boolean) => { if (mainnet == true) { - return ["ethereum", "base", "arbitrum", "megaeth", "katana", "polygon", "bsc"] as ChainName[]; + return [ + "ethereum", + "base", + "arbitrum", + "megaeth", + "katana", + "polygon", + "bsc", + "solanaMainnet" + ] as ChainName[]; } else return [ "sepolia", @@ -229,6 +284,26 @@ export const coinList = (mainnet: boolean) => { name: "usdc.e", chainId: polygon.id, decimals: 6 + }, + { + address: ADDRESS_ZERO, + name: "sol", + chainId: solanaMainnet.id, + decimals: 9 + }, + { + // So11111111111111111111111111111111111111112 + address: `0x069b8857feab8184fb687f634618c035dac439dc1aeb3b5598a0f00000000001`, + name: "wsol", + chainId: solanaMainnet.id, + decimals: 9 + }, + { + // EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + address: `0xc6fa7af3bedbad3a3d65f36aabc97431b1bbe4c2d2f6e0e47ca60203452f5d61`, + name: "usdc", + chainId: solanaMainnet.id, + decimals: 6 } ] as const; else @@ -365,7 +440,8 @@ export const polymerChainIds = { katana: katana.id, bsc: bsc.id, polygon: polygon.id, - solanaDevnet: solanaDevnet.id + solanaDevnet: solanaDevnet.id, + solanaMainnet: solanaMainnet.id } as const; export type Verifier = "wormhole" | "polymer"; diff --git a/src/lib/libraries/coreDeps.ts b/src/lib/libraries/coreDeps.ts index 8ef27bf..c129555 100644 --- a/src/lib/libraries/coreDeps.ts +++ b/src/lib/libraries/coreDeps.ts @@ -4,7 +4,7 @@ import { INPUT_SETTLER_COMPACT_LIFI, MULTICHAIN_INPUT_SETTLER_COMPACT, POLYMER_ORACLE, - SOLANA_OUTPUT_SETTLER_PDA, + SOLANA_PDAS, WORMHOLE_ORACLE } from "$lib/config"; import type { IntentDeps, OrderContainerValidationDeps } from "@lifi/intent"; @@ -24,7 +24,8 @@ export const intentDeps: IntentDeps = { return undefined; }, getSettler(chainId) { - if (chainId === BigInt(chainMap.solanaDevnet.id)) return SOLANA_OUTPUT_SETTLER_PDA; + if (chainId === BigInt(chainMap.solanaDevnet.id)) return SOLANA_PDAS.devnet.OUTPUT_SETTLER; + if (chainId === BigInt(chainMap.solanaMainnet.id)) return SOLANA_PDAS.mainnet.OUTPUT_SETTLER; return undefined; } }; @@ -55,6 +56,6 @@ export const orderValidationDeps: OrderContainerValidationDeps = { return allowed; }, allowedOutputSettlers() { - return [COIN_FILLER, SOLANA_OUTPUT_SETTLER_PDA]; + return [COIN_FILLER, SOLANA_PDAS.devnet.OUTPUT_SETTLER, SOLANA_PDAS.mainnet.OUTPUT_SETTLER]; } }; From 6889e8c6abcb5987e6f390a6a88f46b5d7748301 Mon Sep 17 00:00:00 2001 From: Asem- Abdelhady Date: Fri, 13 Mar 2026 20:19:56 +0100 Subject: [PATCH 13/14] refactor: make Solana integration generic (not devnet-specific) - Replace solanaDevnetConnection/solanaMainnetConnection exports with getSolanaConnection(chainId) dispatcher and isSolanaChain(chainId) helper - Store solana balances keyed by chain ID (number) instead of "solanaDevnet" string - All callers now use isSolanaChain() / getSolanaConnection() so the code works transparently for both devnet and mainnet Co-Authored-By: Claude Sonnet 4.6 --- src/lib/components/InputTokenModal.svelte | 11 +++++------ src/lib/config.ts | 18 ++++++++++++------ src/lib/libraries/intentFactory.ts | 8 ++++---- src/lib/screens/IssueIntent.svelte | 12 ++++++------ src/lib/state.svelte.ts | 17 +++++++++-------- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/lib/components/InputTokenModal.svelte b/src/lib/components/InputTokenModal.svelte index 5381e54..84092a1 100644 --- a/src/lib/components/InputTokenModal.svelte +++ b/src/lib/components/InputTokenModal.svelte @@ -1,5 +1,5 @@