@aurora-is-near/intents-swap-widget-stellar 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import { Asset } from '@stellar/stellar-sdk';
2
+ export declare const RPC_ENDPOINTS: string[];
3
+ export declare const USDC_ASSET: Asset;
@@ -0,0 +1,4 @@
1
+ export declare const fetchNativeBalances: (publicKey: string) => Promise<{
2
+ xlmStroops: string;
3
+ usdcStroops: string;
4
+ }>;
@@ -0,0 +1,3 @@
1
+ export { stellar } from './plugin';
2
+ export { makeTransfer } from './makeTransfer';
3
+ export type { MakeTransferOptions } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ import { Asset as T, xdr as o, StrKey as K, rpc as x, Operation as A, TransactionBuilder as P, Networks as m, BASE_FEE as X, Memo as d } from "@stellar/stellar-sdk";
2
+ import C from "axios";
3
+ const S = [
4
+ "https://sorobanrpc.stellar.org",
5
+ "https://rpc.ankr.com/stellar_soroban",
6
+ "https://stellar-soroban-public.nodies.app"
7
+ ], E = new T(
8
+ "USDC",
9
+ "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
10
+ ), D = async (t) => {
11
+ const n = o.PublicKey.publicKeyTypeEd25519(
12
+ K.decodeEd25519PublicKey(t)
13
+ ), b = o.LedgerKey.account(
14
+ new o.LedgerKeyAccount({ accountId: n })
15
+ ).toXDR("base64"), a = o.LedgerKey.trustline(
16
+ new o.LedgerKeyTrustLine({
17
+ accountId: n,
18
+ asset: E.toTrustLineXDRObject()
19
+ })
20
+ ).toXDR("base64"), c = {
21
+ id: 1,
22
+ jsonrpc: "2.0",
23
+ method: "getLedgerEntries",
24
+ params: { keys: [b, a] }
25
+ };
26
+ for (const p of S)
27
+ try {
28
+ const i = (await C.post(p, c, {
29
+ headers: { "Content-Type": "application/json" },
30
+ timeout: 3e3
31
+ })).data?.result?.entries;
32
+ if (!i || i.length === 0)
33
+ continue;
34
+ let u = "0", f = "0";
35
+ return i.forEach((l) => {
36
+ if (!l.xdr)
37
+ return;
38
+ const r = o.LedgerEntryData.fromXDR(l.xdr, "base64");
39
+ r.switch().name === "account" && (u = r.account().balance().toString()), r.switch().name === "trustline" && (f = r.trustLine().balance().toString());
40
+ }), { xlmStroops: u, usdcStroops: f };
41
+ } catch {
42
+ continue;
43
+ }
44
+ return { xlmStroops: "0", usdcStroops: "0" };
45
+ }, $ = "https://stellar.expert/explorer/public/tx/", B = (t) => {
46
+ if (!t)
47
+ return d.none();
48
+ if (/^\d+$/.test(t))
49
+ return d.id(t);
50
+ if (Buffer.from(t).length <= 28)
51
+ return d.text(t);
52
+ if (/^g[0-7a-z]{55}$/.test(t)) {
53
+ const n = K.decodeEd25519PublicKey(
54
+ t.toUpperCase()
55
+ );
56
+ return d.hash(n);
57
+ }
58
+ if (/^[0-9a-fA-F]{64}$/.test(t))
59
+ return d.hash(t);
60
+ throw new Error(`Unsupported Stellar memo format: ${t}`);
61
+ }, U = async (t, {
62
+ provider: n,
63
+ explorerBaseUrl: b = $
64
+ }) => {
65
+ if (!n.publicKey)
66
+ throw new Error("No public key found in Stellar provider.");
67
+ if (!t.memo)
68
+ throw new Error("No memo provided.");
69
+ let a = null, c = null;
70
+ for (const e of S)
71
+ try {
72
+ const y = new x.Server(e);
73
+ c = await y.getAccount(n.publicKey), a = y;
74
+ break;
75
+ } catch {
76
+ }
77
+ if (!a || !c)
78
+ throw new Error("Could not connect to Stellar RPC to load account data.");
79
+ const p = BigInt(t.amount), R = p / 10000000n, i = (p % 10000000n).toString().padStart(7, "0"), u = `${R}.${i}`.replace(/\.?0+$/, ""), f = t.tokenAddress === E.issuer ? A.payment({
80
+ destination: t.address,
81
+ asset: E,
82
+ amount: u
83
+ }) : A.payment({
84
+ destination: t.address,
85
+ asset: T.native(),
86
+ amount: u
87
+ }), l = new P(c, {
88
+ fee: X,
89
+ networkPassphrase: m.PUBLIC,
90
+ memo: B(t.memo)
91
+ }).addOperation(f).setTimeout(30).build();
92
+ let r;
93
+ try {
94
+ const e = await n.signTransaction(l.toXDR(), {
95
+ networkPassphrase: m.PUBLIC,
96
+ address: n.publicKey
97
+ });
98
+ r = typeof e == "string" ? e : e.signedTxXdr;
99
+ } catch (e) {
100
+ const y = e instanceof Error ? e.message : String(e ?? ""), L = e && typeof e == "object" && "code" in e ? String(e.code) : "", h = `${y} ${L}`.toLowerCase();
101
+ if (h.includes("unsupported") || h.includes("arity") || h.includes("number of arguments") || h.includes("arguments")) {
102
+ const w = await n.signTransaction(l.toXDR());
103
+ r = typeof w == "string" ? w : w.signedTxXdr;
104
+ } else
105
+ throw e;
106
+ }
107
+ if (!r)
108
+ throw new Error("Transaction signing failed.");
109
+ const g = P.fromXDR(
110
+ r,
111
+ m.PUBLIC
112
+ ), s = await a.sendTransaction(g);
113
+ if (s.status === "ERROR" || s.status === "TRY_AGAIN_LATER")
114
+ throw new Error(
115
+ `Stellar transaction failed to submit with status ${s.status}. Hash: ${s.hash}`
116
+ );
117
+ return {
118
+ hash: s.hash,
119
+ transactionLink: `${b}${s.hash}`
120
+ };
121
+ }, O = {
122
+ makeTransfer: U,
123
+ decodePublicKey: (t) => {
124
+ if (!t.publicKey)
125
+ throw new Error("No public key found in Stellar provider.");
126
+ return K.decodeEd25519PublicKey(t.publicKey);
127
+ },
128
+ getNativeBalances: (t) => t.publicKey ? D(t.publicKey) : Promise.resolve({ xlmStroops: "0", usdcStroops: "0" })
129
+ };
130
+ export {
131
+ U as makeTransfer,
132
+ O as stellar
133
+ };
134
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/constants.ts","../src/fetchNativeBalances.ts","../src/makeTransfer.ts","../src/plugin.ts"],"sourcesContent":["import { Asset } from '@stellar/stellar-sdk';\n\nexport const RPC_ENDPOINTS = [\n 'https://sorobanrpc.stellar.org',\n 'https://rpc.ankr.com/stellar_soroban',\n 'https://stellar-soroban-public.nodies.app',\n];\n\nexport const USDC_ASSET = new Asset(\n 'USDC',\n 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN',\n);\n","import { StrKey, xdr } from '@stellar/stellar-sdk';\nimport axios from 'axios';\n\nimport { RPC_ENDPOINTS, USDC_ASSET } from './constants';\n\nexport const fetchNativeBalances = async (publicKey: string) => {\n const accountPubKey = xdr.PublicKey.publicKeyTypeEd25519(\n StrKey.decodeEd25519PublicKey(publicKey),\n );\n\n const accountKeyXdr = xdr.LedgerKey.account(\n new xdr.LedgerKeyAccount({ accountId: accountPubKey }),\n ).toXDR('base64');\n\n const trustlineKeyXdr = xdr.LedgerKey.trustline(\n new xdr.LedgerKeyTrustLine({\n accountId: accountPubKey,\n asset: USDC_ASSET.toTrustLineXDRObject(),\n }),\n ).toXDR('base64');\n\n const requestPayload = {\n id: 1,\n jsonrpc: '2.0',\n method: 'getLedgerEntries',\n params: { keys: [accountKeyXdr, trustlineKeyXdr] },\n };\n\n // eslint-disable-next-line no-restricted-syntax\n for (const baseURL of RPC_ENDPOINTS) {\n try {\n // eslint-disable-next-line no-await-in-loop\n const response = await axios.post<{\n result: { entries: { xdr: string }[] };\n }>(baseURL, requestPayload, {\n headers: { 'Content-Type': 'application/json' },\n timeout: 3000,\n });\n\n const entries = response.data?.result?.entries;\n\n if (!entries || entries.length === 0) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n let xlmStroops = '0';\n let usdcStroops = '0';\n\n entries.forEach((entry) => {\n if (!entry.xdr) {\n return;\n }\n\n const entryData = xdr.LedgerEntryData.fromXDR(entry.xdr, 'base64');\n\n if (entryData.switch().name === 'account') {\n xlmStroops = entryData.account().balance().toString();\n }\n\n if (entryData.switch().name === 'trustline') {\n usdcStroops = entryData.trustLine().balance().toString();\n }\n });\n\n return { xlmStroops, usdcStroops };\n } catch {\n // eslint-disable-next-line no-continue\n continue;\n }\n }\n\n return { xlmStroops: '0', usdcStroops: '0' };\n};\n","import {\n Asset,\n BASE_FEE,\n Memo,\n Networks,\n Operation,\n rpc,\n StrKey,\n Transaction,\n TransactionBuilder,\n} from '@stellar/stellar-sdk';\nimport type {\n MakeTransferArgs,\n TransferResult,\n} from '@aurora-is-near/intents-swap-widget';\n\nimport { RPC_ENDPOINTS, USDC_ASSET } from './constants';\nimport type { MakeTransferOptions } from './types';\n\nconst DEFAULT_EXPLORER_BASE_URL = 'https://stellar.expert/explorer/public/tx/';\n\nconst createMemo = (memoString: string): Memo => {\n if (!memoString) {\n return Memo.none();\n }\n\n // 1. If it's a numeric ID\n if (/^\\d+$/.test(memoString)) {\n return Memo.id(memoString);\n }\n\n // 2. If it's a standard text memo (28 chars or less)\n if (Buffer.from(memoString).length <= 28) {\n return Memo.text(memoString);\n }\n\n // 3. If the memo is a lowercase Stellar public key (56 chars starting with g)\n // We must convert it back to uppercase to decode it, then use the 32-byte raw public key as a MemoHash\n if (/^g[0-7a-z]{55}$/.test(memoString)) {\n const rawPublicKeyBytes = StrKey.decodeEd25519PublicKey(\n memoString.toUpperCase(),\n );\n\n return Memo.hash(rawPublicKeyBytes);\n }\n\n // 4. If the memo is a 64-character hex string\n if (/^[0-9a-fA-F]{64}$/.test(memoString)) {\n return Memo.hash(memoString);\n }\n\n throw new Error(`Unsupported Stellar memo format: ${memoString}`);\n};\n\nexport const makeTransfer = async (\n args: MakeTransferArgs & { memo?: string },\n {\n provider,\n explorerBaseUrl = DEFAULT_EXPLORER_BASE_URL,\n }: MakeTransferOptions,\n): Promise<TransferResult> => {\n if (!provider.publicKey) {\n throw new Error('No public key found in Stellar provider.');\n }\n\n if (!args.memo) {\n throw new Error('No memo provided.');\n }\n\n // 1. Init RPC Server with failover logic\n let rpcServer: rpc.Server | null = null;\n let sourceAccount = null;\n\n // eslint-disable-next-line no-restricted-syntax\n for (const url of RPC_ENDPOINTS) {\n try {\n const tempServer = new rpc.Server(url);\n\n // eslint-disable-next-line no-await-in-loop\n sourceAccount = await tempServer.getAccount(provider.publicKey);\n rpcServer = tempServer;\n break;\n } catch {\n // just continue on error\n }\n }\n\n if (!rpcServer || !sourceAccount) {\n throw new Error('Could not connect to Stellar RPC to load account data.');\n }\n\n const rawAmount = BigInt(args.amount);\n const whole = rawAmount / 10_000_000n;\n const fraction = (rawAmount % 10_000_000n).toString().padStart(7, '0');\n const txAmount = `${whole}.${fraction}`.replace(/\\.?0+$/, '');\n\n // 2. Build the payment operation\n const paymentOp =\n args.tokenAddress === USDC_ASSET.issuer\n ? Operation.payment({\n destination: args.address,\n asset: USDC_ASSET,\n amount: txAmount,\n })\n : Operation.payment({\n destination: args.address,\n asset: Asset.native(),\n amount: txAmount,\n });\n\n // 3. Build Transaction\n const transaction = new TransactionBuilder(sourceAccount, {\n fee: BASE_FEE,\n networkPassphrase: Networks.PUBLIC,\n memo: createMemo(args.memo),\n })\n .addOperation(paymentOp)\n .setTimeout(30)\n .build();\n\n // 4. Request Signature from Wallet\n let signedTxXdr: string;\n\n try {\n // Try the standard Wallets Kit signature (2 arguments)\n const result = await provider.signTransaction(transaction.toXDR(), {\n networkPassphrase: Networks.PUBLIC,\n address: provider.publicKey,\n });\n\n signedTxXdr = typeof result === 'string' ? result : result.signedTxXdr;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err ?? '');\n const code =\n err && typeof err === 'object' && 'code' in err\n ? String((err as { code: unknown }).code)\n : '';\n\n const combined = `${msg} ${code}`.toLowerCase();\n\n const isUnsupportedArity =\n combined.includes('unsupported') ||\n combined.includes('arity') ||\n combined.includes('number of arguments') ||\n combined.includes('arguments');\n\n if (isUnsupportedArity) {\n // Fallback: provider strictly expects 1 argument (e.g. Freighter direct API)\n const result = await provider.signTransaction(transaction.toXDR());\n\n signedTxXdr = typeof result === 'string' ? result : result.signedTxXdr;\n } else {\n throw err;\n }\n }\n\n if (!signedTxXdr) {\n throw new Error('Transaction signing failed.');\n }\n\n // 5. Reconstruct signed transaction from XDR\n const signedTx = TransactionBuilder.fromXDR(\n signedTxXdr,\n Networks.PUBLIC,\n ) as Transaction;\n\n // 6. Submit Transaction to RPC\n const submitResult = await rpcServer.sendTransaction(signedTx);\n\n if (\n submitResult.status === 'ERROR' ||\n submitResult.status === 'TRY_AGAIN_LATER'\n ) {\n throw new Error(\n `Stellar transaction failed to submit with status ${submitResult.status}. Hash: ${submitResult.hash}`,\n );\n }\n\n return {\n hash: submitResult.hash,\n transactionLink: `${explorerBaseUrl}${submitResult.hash}`,\n };\n};\n","import { StrKey } from '@stellar/stellar-sdk';\nimport type { StellarNetworkPlugin } from '@aurora-is-near/intents-swap-widget';\n\nimport { fetchNativeBalances } from './fetchNativeBalances';\nimport { makeTransfer } from './makeTransfer';\n\nexport const stellar: StellarNetworkPlugin = {\n makeTransfer,\n decodePublicKey: (provider) => {\n if (!provider.publicKey) {\n throw new Error('No public key found in Stellar provider.');\n }\n\n return StrKey.decodeEd25519PublicKey(provider.publicKey);\n },\n getNativeBalances: (provider) => {\n if (!provider.publicKey) {\n return Promise.resolve({ xlmStroops: '0', usdcStroops: '0' });\n }\n\n return fetchNativeBalances(provider.publicKey);\n },\n};\n"],"names":["RPC_ENDPOINTS","USDC_ASSET","Asset","fetchNativeBalances","publicKey","accountPubKey","xdr","StrKey","accountKeyXdr","trustlineKeyXdr","requestPayload","baseURL","entries","axios","xlmStroops","usdcStroops","entry","entryData","DEFAULT_EXPLORER_BASE_URL","createMemo","memoString","Memo","rawPublicKeyBytes","makeTransfer","args","provider","explorerBaseUrl","rpcServer","sourceAccount","url","tempServer","rpc","rawAmount","whole","fraction","txAmount","paymentOp","Operation","transaction","TransactionBuilder","BASE_FEE","Networks","signedTxXdr","result","err","msg","code","combined","signedTx","submitResult","stellar"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { MakeTransferArgs, TransferResult } from '@aurora-is-near/intents-swap-widget';
2
+ import { MakeTransferOptions } from './types';
3
+ export declare const makeTransfer: (args: MakeTransferArgs & {
4
+ memo?: string;
5
+ }, { provider, explorerBaseUrl, }: MakeTransferOptions) => Promise<TransferResult>;
@@ -0,0 +1,2 @@
1
+ import { StellarNetworkPlugin } from '@aurora-is-near/intents-swap-widget';
2
+ export declare const stellar: StellarNetworkPlugin;
@@ -0,0 +1,5 @@
1
+ import { StellarProvider } from '@aurora-is-near/intents-swap-widget';
2
+ export type MakeTransferOptions = {
3
+ provider: StellarProvider;
4
+ explorerBaseUrl?: string;
5
+ };
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@aurora-is-near/intents-swap-widget-stellar",
3
+ "version": "7.1.0",
4
+ "description": "Stellar connector for the Intents swap widget",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "module": "./dist/index.js",
9
+ "type": "module",
10
+ "scripts": {
11
+ "typecheck": "tsc --noEmit",
12
+ "lint": "eslint . --ext .js,.ts,.tsx",
13
+ "clean": "rimraf dist",
14
+ "prebuild": "yarn clean",
15
+ "build": "vite build"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.org/"
20
+ },
21
+ "files": [
22
+ "src",
23
+ "dist"
24
+ ],
25
+ "exports": {
26
+ ".": "./dist/index.js"
27
+ },
28
+ "peerDependencies": {
29
+ "@aurora-is-near/intents-swap-widget": "^7.1.0"
30
+ },
31
+ "devDependencies": {
32
+ "@aurora-is-near/intents-swap-widget": "^7.1.0"
33
+ },
34
+ "dependencies": {
35
+ "@stellar/stellar-sdk": "^14.6.1",
36
+ "axios": "^1.10.0"
37
+ }
38
+ }
@@ -0,0 +1,12 @@
1
+ import { Asset } from '@stellar/stellar-sdk';
2
+
3
+ export const RPC_ENDPOINTS = [
4
+ 'https://sorobanrpc.stellar.org',
5
+ 'https://rpc.ankr.com/stellar_soroban',
6
+ 'https://stellar-soroban-public.nodies.app',
7
+ ];
8
+
9
+ export const USDC_ASSET = new Asset(
10
+ 'USDC',
11
+ 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN',
12
+ );
@@ -0,0 +1,74 @@
1
+ import { StrKey, xdr } from '@stellar/stellar-sdk';
2
+ import axios from 'axios';
3
+
4
+ import { RPC_ENDPOINTS, USDC_ASSET } from './constants';
5
+
6
+ export const fetchNativeBalances = async (publicKey: string) => {
7
+ const accountPubKey = xdr.PublicKey.publicKeyTypeEd25519(
8
+ StrKey.decodeEd25519PublicKey(publicKey),
9
+ );
10
+
11
+ const accountKeyXdr = xdr.LedgerKey.account(
12
+ new xdr.LedgerKeyAccount({ accountId: accountPubKey }),
13
+ ).toXDR('base64');
14
+
15
+ const trustlineKeyXdr = xdr.LedgerKey.trustline(
16
+ new xdr.LedgerKeyTrustLine({
17
+ accountId: accountPubKey,
18
+ asset: USDC_ASSET.toTrustLineXDRObject(),
19
+ }),
20
+ ).toXDR('base64');
21
+
22
+ const requestPayload = {
23
+ id: 1,
24
+ jsonrpc: '2.0',
25
+ method: 'getLedgerEntries',
26
+ params: { keys: [accountKeyXdr, trustlineKeyXdr] },
27
+ };
28
+
29
+ // eslint-disable-next-line no-restricted-syntax
30
+ for (const baseURL of RPC_ENDPOINTS) {
31
+ try {
32
+ // eslint-disable-next-line no-await-in-loop
33
+ const response = await axios.post<{
34
+ result: { entries: { xdr: string }[] };
35
+ }>(baseURL, requestPayload, {
36
+ headers: { 'Content-Type': 'application/json' },
37
+ timeout: 3000,
38
+ });
39
+
40
+ const entries = response.data?.result?.entries;
41
+
42
+ if (!entries || entries.length === 0) {
43
+ // eslint-disable-next-line no-continue
44
+ continue;
45
+ }
46
+
47
+ let xlmStroops = '0';
48
+ let usdcStroops = '0';
49
+
50
+ entries.forEach((entry) => {
51
+ if (!entry.xdr) {
52
+ return;
53
+ }
54
+
55
+ const entryData = xdr.LedgerEntryData.fromXDR(entry.xdr, 'base64');
56
+
57
+ if (entryData.switch().name === 'account') {
58
+ xlmStroops = entryData.account().balance().toString();
59
+ }
60
+
61
+ if (entryData.switch().name === 'trustline') {
62
+ usdcStroops = entryData.trustLine().balance().toString();
63
+ }
64
+ });
65
+
66
+ return { xlmStroops, usdcStroops };
67
+ } catch {
68
+ // eslint-disable-next-line no-continue
69
+ continue;
70
+ }
71
+ }
72
+
73
+ return { xlmStroops: '0', usdcStroops: '0' };
74
+ };
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { stellar } from './plugin';
2
+ export { makeTransfer } from './makeTransfer';
3
+ export type { MakeTransferOptions } from './types';
@@ -0,0 +1,183 @@
1
+ import {
2
+ Asset,
3
+ BASE_FEE,
4
+ Memo,
5
+ Networks,
6
+ Operation,
7
+ rpc,
8
+ StrKey,
9
+ Transaction,
10
+ TransactionBuilder,
11
+ } from '@stellar/stellar-sdk';
12
+ import type {
13
+ MakeTransferArgs,
14
+ TransferResult,
15
+ } from '@aurora-is-near/intents-swap-widget';
16
+
17
+ import { RPC_ENDPOINTS, USDC_ASSET } from './constants';
18
+ import type { MakeTransferOptions } from './types';
19
+
20
+ const DEFAULT_EXPLORER_BASE_URL = 'https://stellar.expert/explorer/public/tx/';
21
+
22
+ const createMemo = (memoString: string): Memo => {
23
+ if (!memoString) {
24
+ return Memo.none();
25
+ }
26
+
27
+ // 1. If it's a numeric ID
28
+ if (/^\d+$/.test(memoString)) {
29
+ return Memo.id(memoString);
30
+ }
31
+
32
+ // 2. If it's a standard text memo (28 chars or less)
33
+ if (Buffer.from(memoString).length <= 28) {
34
+ return Memo.text(memoString);
35
+ }
36
+
37
+ // 3. If the memo is a lowercase Stellar public key (56 chars starting with g)
38
+ // We must convert it back to uppercase to decode it, then use the 32-byte raw public key as a MemoHash
39
+ if (/^g[0-7a-z]{55}$/.test(memoString)) {
40
+ const rawPublicKeyBytes = StrKey.decodeEd25519PublicKey(
41
+ memoString.toUpperCase(),
42
+ );
43
+
44
+ return Memo.hash(rawPublicKeyBytes);
45
+ }
46
+
47
+ // 4. If the memo is a 64-character hex string
48
+ if (/^[0-9a-fA-F]{64}$/.test(memoString)) {
49
+ return Memo.hash(memoString);
50
+ }
51
+
52
+ throw new Error(`Unsupported Stellar memo format: ${memoString}`);
53
+ };
54
+
55
+ export const makeTransfer = async (
56
+ args: MakeTransferArgs & { memo?: string },
57
+ {
58
+ provider,
59
+ explorerBaseUrl = DEFAULT_EXPLORER_BASE_URL,
60
+ }: MakeTransferOptions,
61
+ ): Promise<TransferResult> => {
62
+ if (!provider.publicKey) {
63
+ throw new Error('No public key found in Stellar provider.');
64
+ }
65
+
66
+ if (!args.memo) {
67
+ throw new Error('No memo provided.');
68
+ }
69
+
70
+ // 1. Init RPC Server with failover logic
71
+ let rpcServer: rpc.Server | null = null;
72
+ let sourceAccount = null;
73
+
74
+ // eslint-disable-next-line no-restricted-syntax
75
+ for (const url of RPC_ENDPOINTS) {
76
+ try {
77
+ const tempServer = new rpc.Server(url);
78
+
79
+ // eslint-disable-next-line no-await-in-loop
80
+ sourceAccount = await tempServer.getAccount(provider.publicKey);
81
+ rpcServer = tempServer;
82
+ break;
83
+ } catch {
84
+ // just continue on error
85
+ }
86
+ }
87
+
88
+ if (!rpcServer || !sourceAccount) {
89
+ throw new Error('Could not connect to Stellar RPC to load account data.');
90
+ }
91
+
92
+ const rawAmount = BigInt(args.amount);
93
+ const whole = rawAmount / 10_000_000n;
94
+ const fraction = (rawAmount % 10_000_000n).toString().padStart(7, '0');
95
+ const txAmount = `${whole}.${fraction}`.replace(/\.?0+$/, '');
96
+
97
+ // 2. Build the payment operation
98
+ const paymentOp =
99
+ args.tokenAddress === USDC_ASSET.issuer
100
+ ? Operation.payment({
101
+ destination: args.address,
102
+ asset: USDC_ASSET,
103
+ amount: txAmount,
104
+ })
105
+ : Operation.payment({
106
+ destination: args.address,
107
+ asset: Asset.native(),
108
+ amount: txAmount,
109
+ });
110
+
111
+ // 3. Build Transaction
112
+ const transaction = new TransactionBuilder(sourceAccount, {
113
+ fee: BASE_FEE,
114
+ networkPassphrase: Networks.PUBLIC,
115
+ memo: createMemo(args.memo),
116
+ })
117
+ .addOperation(paymentOp)
118
+ .setTimeout(30)
119
+ .build();
120
+
121
+ // 4. Request Signature from Wallet
122
+ let signedTxXdr: string;
123
+
124
+ try {
125
+ // Try the standard Wallets Kit signature (2 arguments)
126
+ const result = await provider.signTransaction(transaction.toXDR(), {
127
+ networkPassphrase: Networks.PUBLIC,
128
+ address: provider.publicKey,
129
+ });
130
+
131
+ signedTxXdr = typeof result === 'string' ? result : result.signedTxXdr;
132
+ } catch (err) {
133
+ const msg = err instanceof Error ? err.message : String(err ?? '');
134
+ const code =
135
+ err && typeof err === 'object' && 'code' in err
136
+ ? String((err as { code: unknown }).code)
137
+ : '';
138
+
139
+ const combined = `${msg} ${code}`.toLowerCase();
140
+
141
+ const isUnsupportedArity =
142
+ combined.includes('unsupported') ||
143
+ combined.includes('arity') ||
144
+ combined.includes('number of arguments') ||
145
+ combined.includes('arguments');
146
+
147
+ if (isUnsupportedArity) {
148
+ // Fallback: provider strictly expects 1 argument (e.g. Freighter direct API)
149
+ const result = await provider.signTransaction(transaction.toXDR());
150
+
151
+ signedTxXdr = typeof result === 'string' ? result : result.signedTxXdr;
152
+ } else {
153
+ throw err;
154
+ }
155
+ }
156
+
157
+ if (!signedTxXdr) {
158
+ throw new Error('Transaction signing failed.');
159
+ }
160
+
161
+ // 5. Reconstruct signed transaction from XDR
162
+ const signedTx = TransactionBuilder.fromXDR(
163
+ signedTxXdr,
164
+ Networks.PUBLIC,
165
+ ) as Transaction;
166
+
167
+ // 6. Submit Transaction to RPC
168
+ const submitResult = await rpcServer.sendTransaction(signedTx);
169
+
170
+ if (
171
+ submitResult.status === 'ERROR' ||
172
+ submitResult.status === 'TRY_AGAIN_LATER'
173
+ ) {
174
+ throw new Error(
175
+ `Stellar transaction failed to submit with status ${submitResult.status}. Hash: ${submitResult.hash}`,
176
+ );
177
+ }
178
+
179
+ return {
180
+ hash: submitResult.hash,
181
+ transactionLink: `${explorerBaseUrl}${submitResult.hash}`,
182
+ };
183
+ };
package/src/plugin.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { StrKey } from '@stellar/stellar-sdk';
2
+ import type { StellarNetworkPlugin } from '@aurora-is-near/intents-swap-widget';
3
+
4
+ import { fetchNativeBalances } from './fetchNativeBalances';
5
+ import { makeTransfer } from './makeTransfer';
6
+
7
+ export const stellar: StellarNetworkPlugin = {
8
+ makeTransfer,
9
+ decodePublicKey: (provider) => {
10
+ if (!provider.publicKey) {
11
+ throw new Error('No public key found in Stellar provider.');
12
+ }
13
+
14
+ return StrKey.decodeEd25519PublicKey(provider.publicKey);
15
+ },
16
+ getNativeBalances: (provider) => {
17
+ if (!provider.publicKey) {
18
+ return Promise.resolve({ xlmStroops: '0', usdcStroops: '0' });
19
+ }
20
+
21
+ return fetchNativeBalances(provider.publicKey);
22
+ },
23
+ };
package/src/types.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { StellarProvider } from '@aurora-is-near/intents-swap-widget';
2
+
3
+ export type MakeTransferOptions = {
4
+ provider: StellarProvider;
5
+ explorerBaseUrl?: string;
6
+ };