@reown/appkit-solana-react-native 2.0.0-alpha.4 → 2.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/adapter.js +69 -8
- package/lib/commonjs/adapter.js.map +1 -1
- package/lib/commonjs/connectors/PhantomConnector.js +4 -1
- package/lib/commonjs/connectors/PhantomConnector.js.map +1 -1
- package/lib/commonjs/connectors/SolflareConnector.js +4 -1
- package/lib/commonjs/connectors/SolflareConnector.js.map +1 -1
- package/lib/commonjs/utils/createSPLTokenTransaction.js +96 -0
- package/lib/commonjs/utils/createSPLTokenTransaction.js.map +1 -0
- package/lib/commonjs/utils/createSendTransaction.js +3 -17
- package/lib/commonjs/utils/createSendTransaction.js.map +1 -1
- package/lib/module/adapter.js +69 -8
- package/lib/module/adapter.js.map +1 -1
- package/lib/module/connectors/PhantomConnector.js +4 -1
- package/lib/module/connectors/PhantomConnector.js.map +1 -1
- package/lib/module/connectors/SolflareConnector.js +4 -1
- package/lib/module/connectors/SolflareConnector.js.map +1 -1
- package/lib/module/utils/createSPLTokenTransaction.js +92 -0
- package/lib/module/utils/createSPLTokenTransaction.js.map +1 -0
- package/lib/module/utils/createSendTransaction.js +4 -19
- package/lib/module/utils/createSendTransaction.js.map +1 -1
- package/lib/typescript/adapter.d.ts +2 -0
- package/lib/typescript/adapter.d.ts.map +1 -1
- package/lib/typescript/connectors/PhantomConnector.d.ts.map +1 -1
- package/lib/typescript/connectors/SolflareConnector.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +8 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils/createSPLTokenTransaction.d.ts +4 -0
- package/lib/typescript/utils/createSPLTokenTransaction.d.ts.map +1 -0
- package/lib/typescript/utils/createSendTransaction.d.ts +2 -2
- package/lib/typescript/utils/createSendTransaction.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/adapter.ts +80 -12
- package/src/connectors/PhantomConnector.ts +4 -1
- package/src/connectors/SolflareConnector.ts +4 -1
- package/src/types.ts +9 -0
- package/src/utils/createSPLTokenTransaction.ts +152 -0
- package/src/utils/createSendTransaction.ts +3 -19
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, TokenAccountNotFoundError, createAssociatedTokenAccountInstruction, createTransferCheckedInstruction, getAccount, getAssociatedTokenAddressSync, getMint } from '@solana/spl-token';
|
|
4
|
+
import { ComputeBudgetProgram, PublicKey, Transaction } from '@solana/web3.js';
|
|
5
|
+
const SPL_COMPUTE_BUDGET_CONSTANTS = {
|
|
6
|
+
UNIT_PRICE_MICRO_LAMPORTS: 1000000,
|
|
7
|
+
UNIT_LIMIT_WITH_ATA_CREATION: 400000
|
|
8
|
+
};
|
|
9
|
+
async function getMintOwnerProgramId(connection, mint) {
|
|
10
|
+
const info = await connection.getAccountInfo(mint);
|
|
11
|
+
if (!info) {
|
|
12
|
+
throw new Error('Mint account not found');
|
|
13
|
+
}
|
|
14
|
+
if (info.owner.equals(TOKEN_PROGRAM_ID)) {
|
|
15
|
+
return TOKEN_PROGRAM_ID;
|
|
16
|
+
}
|
|
17
|
+
if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) {
|
|
18
|
+
return TOKEN_2022_PROGRAM_ID;
|
|
19
|
+
}
|
|
20
|
+
throw new Error('Unknown mint owner program');
|
|
21
|
+
}
|
|
22
|
+
export async function createSPLTokenTransaction({
|
|
23
|
+
fromAddress,
|
|
24
|
+
toAddress,
|
|
25
|
+
amount,
|
|
26
|
+
tokenMint,
|
|
27
|
+
connection
|
|
28
|
+
}) {
|
|
29
|
+
if (!fromAddress) {
|
|
30
|
+
throw new Error('No public key found');
|
|
31
|
+
}
|
|
32
|
+
if (amount <= 0) {
|
|
33
|
+
throw new Error('Amount must be greater than 0');
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const fromPubkey = new PublicKey(fromAddress);
|
|
37
|
+
const toPubkey = new PublicKey(toAddress);
|
|
38
|
+
const mintPubkey = new PublicKey(tokenMint);
|
|
39
|
+
const programId = await getMintOwnerProgramId(connection, mintPubkey);
|
|
40
|
+
const mintInfo = await getMint(connection, mintPubkey, undefined, programId);
|
|
41
|
+
const decimals = mintInfo.decimals;
|
|
42
|
+
if (decimals < 0) {
|
|
43
|
+
throw new Error('Invalid token decimals');
|
|
44
|
+
}
|
|
45
|
+
const tokenAmount = Math.floor(amount * 10 ** decimals);
|
|
46
|
+
const fromTokenAccount = getAssociatedTokenAddressSync(mintPubkey, fromPubkey, false, programId);
|
|
47
|
+
const toTokenAccount = getAssociatedTokenAddressSync(mintPubkey, toPubkey, false, programId);
|
|
48
|
+
try {
|
|
49
|
+
const fromAccount = await getAccount(connection, fromTokenAccount, undefined, programId);
|
|
50
|
+
if (fromAccount.amount < BigInt(tokenAmount)) {
|
|
51
|
+
throw new Error('Insufficient token balance');
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (error instanceof TokenAccountNotFoundError) {
|
|
55
|
+
throw new Error('Sender does not have a token account for this mint');
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
let shouldCreateATA = false;
|
|
60
|
+
try {
|
|
61
|
+
await getAccount(connection, toTokenAccount, undefined, programId);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error instanceof TokenAccountNotFoundError) {
|
|
64
|
+
shouldCreateATA = true;
|
|
65
|
+
} else {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const instructions = [];
|
|
70
|
+
if (shouldCreateATA) {
|
|
71
|
+
instructions.push(ComputeBudgetProgram.setComputeUnitPrice({
|
|
72
|
+
microLamports: SPL_COMPUTE_BUDGET_CONSTANTS.UNIT_PRICE_MICRO_LAMPORTS
|
|
73
|
+
}), ComputeBudgetProgram.setComputeUnitLimit({
|
|
74
|
+
units: SPL_COMPUTE_BUDGET_CONSTANTS.UNIT_LIMIT_WITH_ATA_CREATION
|
|
75
|
+
}));
|
|
76
|
+
instructions.push(createAssociatedTokenAccountInstruction(fromPubkey, toTokenAccount, toPubkey, mintPubkey, programId));
|
|
77
|
+
}
|
|
78
|
+
instructions.push(createTransferCheckedInstruction(fromTokenAccount, mintPubkey, toTokenAccount, fromPubkey, tokenAmount, decimals, [], programId));
|
|
79
|
+
const {
|
|
80
|
+
blockhash,
|
|
81
|
+
lastValidBlockHeight
|
|
82
|
+
} = await connection.getLatestBlockhash();
|
|
83
|
+
return new Transaction({
|
|
84
|
+
feePayer: fromPubkey,
|
|
85
|
+
blockhash,
|
|
86
|
+
lastValidBlockHeight
|
|
87
|
+
}).add(...instructions);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
throw new Error(`Failed to create SPL token transaction: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=createSPLTokenTransaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TOKEN_2022_PROGRAM_ID","TOKEN_PROGRAM_ID","TokenAccountNotFoundError","createAssociatedTokenAccountInstruction","createTransferCheckedInstruction","getAccount","getAssociatedTokenAddressSync","getMint","ComputeBudgetProgram","PublicKey","Transaction","SPL_COMPUTE_BUDGET_CONSTANTS","UNIT_PRICE_MICRO_LAMPORTS","UNIT_LIMIT_WITH_ATA_CREATION","getMintOwnerProgramId","connection","mint","info","getAccountInfo","Error","owner","equals","createSPLTokenTransaction","fromAddress","toAddress","amount","tokenMint","fromPubkey","toPubkey","mintPubkey","programId","mintInfo","undefined","decimals","tokenAmount","Math","floor","fromTokenAccount","toTokenAccount","fromAccount","BigInt","error","shouldCreateATA","instructions","push","setComputeUnitPrice","microLamports","setComputeUnitLimit","units","blockhash","lastValidBlockHeight","getLatestBlockhash","feePayer","add","message"],"sourceRoot":"../../../src","sources":["utils/createSPLTokenTransaction.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,34 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
// import type { Provider } from '@reown/appkit-utils/solana'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* These constants defines the cost of running the program, allowing to calculate the maximum
|
|
9
|
-
* amount of SOL that can be sent in case of cleaning the account and remove the rent exemption error.
|
|
10
|
-
*/
|
|
11
|
-
const COMPUTE_BUDGET_CONSTANTS = {
|
|
12
|
-
UNIT_PRICE_MICRO_LAMPORTS: 20000000,
|
|
13
|
-
UNIT_LIMIT: 500
|
|
14
|
-
};
|
|
3
|
+
import { LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
|
|
15
4
|
export async function createSendTransaction({
|
|
16
5
|
fromAddress,
|
|
17
6
|
toAddress,
|
|
18
|
-
|
|
7
|
+
amount,
|
|
19
8
|
connection
|
|
20
9
|
}) {
|
|
21
10
|
const fromPubkey = new PublicKey(fromAddress);
|
|
22
11
|
const toPubkey = new PublicKey(toAddress);
|
|
23
|
-
const lamports = Math.floor(
|
|
12
|
+
const lamports = Math.floor(amount * LAMPORTS_PER_SOL);
|
|
24
13
|
const {
|
|
25
14
|
blockhash
|
|
26
15
|
} = await connection.getLatestBlockhash();
|
|
27
|
-
const instructions = [
|
|
28
|
-
microLamports: COMPUTE_BUDGET_CONSTANTS.UNIT_PRICE_MICRO_LAMPORTS
|
|
29
|
-
}), ComputeBudgetProgram.setComputeUnitLimit({
|
|
30
|
-
units: COMPUTE_BUDGET_CONSTANTS.UNIT_LIMIT
|
|
31
|
-
}), SystemProgram.transfer({
|
|
16
|
+
const instructions = [SystemProgram.transfer({
|
|
32
17
|
fromPubkey,
|
|
33
18
|
toPubkey,
|
|
34
19
|
lamports
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["LAMPORTS_PER_SOL","PublicKey","SystemProgram","Transaction","createSendTransaction","fromAddress","toAddress","amount","connection","fromPubkey","toPubkey","lamports","Math","floor","blockhash","getLatestBlockhash","instructions","transfer","transaction","add","feePayer","recentBlockhash"],"sourceRoot":"../../../src","sources":["utils/createSendTransaction.ts"],"mappings":";;AAAA,SAEEA,gBAAgB,EAChBC,SAAS,EACTC,aAAa,EACbC,WAAW,QACN,iBAAiB;AASxB,OAAO,eAAeC,qBAAqBA,CAAC;EAC1CC,WAAW;EACXC,SAAS;EACTC,MAAM;EACNC;AACmB,CAAC,EAAwB;EAC5C,MAAMC,UAAU,GAAG,IAAIR,SAAS,CAACI,WAAW,CAAC;EAC7C,MAAMK,QAAQ,GAAG,IAAIT,SAAS,CAACK,SAAS,CAAC;EACzC,MAAMK,QAAQ,GAAGC,IAAI,CAACC,KAAK,CAACN,MAAM,GAAGP,gBAAgB,CAAC;EAEtD,MAAM;IAAEc;EAAU,CAAC,GAAG,MAAMN,UAAU,CAACO,kBAAkB,CAAC,CAAC;EAE3D,MAAMC,YAAY,GAAG,CACnBd,aAAa,CAACe,QAAQ,CAAC;IACrBR,UAAU;IACVC,QAAQ;IACRC;EACF,CAAC,CAAC,CACH;EAED,MAAMO,WAAW,GAAG,IAAIf,WAAW,CAAC,CAAC,CAACgB,GAAG,CAAC,GAAGH,YAAY,CAAC;EAC1DE,WAAW,CAACE,QAAQ,GAAGX,UAAU;EACjCS,WAAW,CAACG,eAAe,GAAGP,SAAS;EAEvC,OAAOI,WAAW;AACpB","ignoreList":[]}
|
|
@@ -6,6 +6,7 @@ export interface SolanaTransactionData {
|
|
|
6
6
|
amount: number;
|
|
7
7
|
network?: AppKitNetwork;
|
|
8
8
|
rpcUrl?: string;
|
|
9
|
+
tokenMint?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare class SolanaAdapter extends SolanaBaseAdapter {
|
|
11
12
|
private static supportedNamespace;
|
|
@@ -13,6 +14,7 @@ export declare class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
13
14
|
getBalance(params: GetBalanceParams): Promise<GetBalanceResponse>;
|
|
14
15
|
signTransaction<T extends Transaction | VersionedTransaction>(transaction: T, network?: AppKitNetwork): Promise<T>;
|
|
15
16
|
sendTransaction(data: SolanaTransactionData): Promise<string | null>;
|
|
17
|
+
signMessage(address: string, message: string, chainId?: string): Promise<string>;
|
|
16
18
|
switchNetwork(network: AppKitNetwork): Promise<void>;
|
|
17
19
|
getAccounts(): CaipAddress[] | undefined;
|
|
18
20
|
disconnect(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACxB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAc,WAAW,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACxB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAc,WAAW,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAKhF,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA4B;;IASvD,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8CjE,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAChE,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,CAAC,CAAC;IA0FP,eAAe,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA8E3D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiCzF,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1D,WAAW,IAAI,WAAW,EAAE,GAAG,SAAS;IAOxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,qBAAqB,IAAI,cAAc;CAGxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhantomConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/PhantomConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAMvD,qBAAa,gBAAiB,SAAQ,iBAAiB;gBACzC,MAAM,CAAC,EAAE,sBAAsB;IAIlC,aAAa,IAAI,UAAU;
|
|
1
|
+
{"version":3,"file":"PhantomConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/PhantomConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAMvD,qBAAa,gBAAiB,SAAQ,iBAAiB;gBACzC,MAAM,CAAC,EAAE,sBAAsB;IAIlC,aAAa,IAAI,UAAU;IAOpC,SAAS,CAAC,UAAU,IAAI,MAAM;IAI9B,SAAS,CAAC,aAAa,IAAI,MAAM;IAIjC,SAAS,CAAC,wBAAwB,IAAI,MAAM;IAI5C,SAAS,CAAC,yBAAyB,IAAI,MAAM;CAG9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolflareConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/SolflareConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAMxD,qBAAa,iBAAkB,SAAQ,iBAAiB;gBAC1C,MAAM,CAAC,EAAE,uBAAuB;IAInC,aAAa,IAAI,UAAU;
|
|
1
|
+
{"version":3,"file":"SolflareConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/SolflareConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAMxD,qBAAa,iBAAkB,SAAQ,iBAAiB;gBAC1C,MAAM,CAAC,EAAE,uBAAuB;IAInC,aAAa,IAAI,UAAU;IAOpC,SAAS,CAAC,UAAU,IAAI,MAAM;IAI9B,SAAS,CAAC,aAAa,IAAI,MAAM;IAIjC,SAAS,CAAC,wBAAwB,IAAI,MAAM;IAI5C,SAAS,CAAC,yBAAyB,IAAI,MAAM;CAG9C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CaipNetworkId, Namespaces, Storage, WalletInfo } from '@reown/appkit-common-react-native';
|
|
2
2
|
import type nacl from 'tweetnacl';
|
|
3
|
+
import type { Connection } from '@solana/web3.js';
|
|
3
4
|
export interface TokenInfo {
|
|
4
5
|
address: string;
|
|
5
6
|
symbol: string;
|
|
@@ -7,6 +8,13 @@ export interface TokenInfo {
|
|
|
7
8
|
decimals: number;
|
|
8
9
|
logoURI?: string;
|
|
9
10
|
}
|
|
11
|
+
export type SPLTokenTransactionArgs = {
|
|
12
|
+
connection: Connection;
|
|
13
|
+
fromAddress: string;
|
|
14
|
+
toAddress: string;
|
|
15
|
+
amount: number;
|
|
16
|
+
tokenMint: string;
|
|
17
|
+
};
|
|
10
18
|
export type Cluster = 'mainnet-beta' | 'testnet' | 'devnet';
|
|
11
19
|
export type DeeplinkConnectResult = DeeplinkSession;
|
|
12
20
|
export interface DeeplinkSession {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,OAAO,EACP,UAAU,EACX,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Transaction } from '@solana/web3.js';
|
|
2
|
+
import type { SPLTokenTransactionArgs } from '../types';
|
|
3
|
+
export declare function createSPLTokenTransaction({ fromAddress, toAddress, amount, tokenMint, connection }: SPLTokenTransactionArgs): Promise<Transaction>;
|
|
4
|
+
//# sourceMappingURL=createSPLTokenTransaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSPLTokenTransaction.d.ts","sourceRoot":"","sources":["../../../src/utils/createSPLTokenTransaction.ts"],"names":[],"mappings":"AAUA,OAAO,EAIL,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAyBxD,wBAAsB,yBAAyB,CAAC,EAC9C,WAAW,EACX,SAAS,EACT,MAAM,EACN,SAAS,EACT,UAAU,EACX,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuGhD"}
|
|
@@ -3,8 +3,8 @@ type SendTransactionArgs = {
|
|
|
3
3
|
connection: Connection;
|
|
4
4
|
fromAddress: string;
|
|
5
5
|
toAddress: string;
|
|
6
|
-
|
|
6
|
+
amount: number;
|
|
7
7
|
};
|
|
8
|
-
export declare function createSendTransaction({ fromAddress, toAddress,
|
|
8
|
+
export declare function createSendTransaction({ fromAddress, toAddress, amount, connection }: SendTransactionArgs): Promise<Transaction>;
|
|
9
9
|
export {};
|
|
10
10
|
//# sourceMappingURL=createSendTransaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSendTransaction.d.ts","sourceRoot":"","sources":["../../../src/utils/createSendTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"createSendTransaction.d.ts","sourceRoot":"","sources":["../../../src/utils/createSendTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EAIf,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAEzB,KAAK,mBAAmB,GAAG;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,SAAS,EACT,MAAM,EACN,UAAU,EACX,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reown/appkit-solana-react-native",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.6",
|
|
4
4
|
"main": "lib/commonjs/index.js",
|
|
5
5
|
"types": "lib/typescript/index.d.ts",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -30,16 +30,18 @@
|
|
|
30
30
|
"repository": "https://github.com/reown-com/appkit-react-native",
|
|
31
31
|
"author": "Reown (https://discord.gg/reown)",
|
|
32
32
|
"homepage": "https://reown.com/appkit",
|
|
33
|
-
"license": "
|
|
33
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/reown-com/appkit-react-native/issues"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"registry": "https://registry.npmjs.org/",
|
|
39
|
-
"access": "public"
|
|
39
|
+
"access": "public",
|
|
40
|
+
"provenance": true
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"@reown/appkit-common-react-native": "2.0.0-alpha.
|
|
43
|
+
"@reown/appkit-common-react-native": "2.0.0-alpha.6",
|
|
44
|
+
"@solana/spl-token": "0.4.13",
|
|
43
45
|
"@solana/web3.js": "1.98.2",
|
|
44
46
|
"bs58": "6.0.0",
|
|
45
47
|
"tweetnacl": "1.0.3"
|
package/src/adapter.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { getSolanaNativeBalance, getSolanaTokenBalance } from './helpers';
|
|
|
10
10
|
import { Connection, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
11
11
|
import base58 from 'bs58';
|
|
12
12
|
import { createSendTransaction } from './utils/createSendTransaction';
|
|
13
|
+
import { createSPLTokenTransaction } from './utils/createSPLTokenTransaction';
|
|
13
14
|
|
|
14
15
|
export interface SolanaTransactionData {
|
|
15
16
|
fromAddress: string;
|
|
@@ -17,6 +18,7 @@ export interface SolanaTransactionData {
|
|
|
17
18
|
amount: number;
|
|
18
19
|
network?: AppKitNetwork;
|
|
19
20
|
rpcUrl?: string;
|
|
21
|
+
tokenMint?: string;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export class SolanaAdapter extends SolanaBaseAdapter {
|
|
@@ -93,10 +95,22 @@ export class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
try {
|
|
96
|
-
//
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
// Check if this is a deeplink provider (Phantom/Solflare)
|
|
99
|
+
const isDeeplinkProvider =
|
|
100
|
+
this.connector.type === 'phantom' || this.connector.type === 'solflare';
|
|
101
|
+
|
|
102
|
+
// Serialize transaction based on provider type
|
|
103
|
+
let serializedTransaction: string;
|
|
104
|
+
if (isDeeplinkProvider) {
|
|
105
|
+
// Deeplink providers (Phantom/Solflare) expect base58
|
|
106
|
+
const transactionBytes = new Uint8Array(transaction.serialize({ verifySignatures: false }));
|
|
107
|
+
serializedTransaction = base58.encode(transactionBytes);
|
|
108
|
+
} else {
|
|
109
|
+
// WalletConnect providers expect base64 (following WalletConnect standard)
|
|
110
|
+
serializedTransaction = Buffer.from(
|
|
111
|
+
new Uint8Array(transaction.serialize({ verifySignatures: false }))
|
|
112
|
+
).toString('base64');
|
|
113
|
+
}
|
|
100
114
|
|
|
101
115
|
const result = (await provider.request(
|
|
102
116
|
{
|
|
@@ -125,7 +139,20 @@ export class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
125
139
|
|
|
126
140
|
if ('transaction' in result && result.transaction) {
|
|
127
141
|
// New response format - deserialize the signed transaction
|
|
128
|
-
|
|
142
|
+
let decodedTransaction: Buffer;
|
|
143
|
+
|
|
144
|
+
if (isDeeplinkProvider) {
|
|
145
|
+
// Deeplink providers return base58 encoded transactions
|
|
146
|
+
try {
|
|
147
|
+
const decodedBytes = base58.decode(result.transaction);
|
|
148
|
+
decodedTransaction = Buffer.from(decodedBytes);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw new Error('Failed to decode base58 transaction from deeplink provider');
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
// WalletConnect providers return base64 encoded transactions
|
|
154
|
+
decodedTransaction = Buffer.from(result.transaction, 'base64');
|
|
155
|
+
}
|
|
129
156
|
|
|
130
157
|
if (transaction instanceof VersionedTransaction) {
|
|
131
158
|
return VersionedTransaction.deserialize(new Uint8Array(decodedTransaction)) as T;
|
|
@@ -144,7 +171,7 @@ export class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
144
171
|
}
|
|
145
172
|
|
|
146
173
|
async sendTransaction(data: SolanaTransactionData): Promise<string | null> {
|
|
147
|
-
const { fromAddress, toAddress, amount, network, rpcUrl } = data;
|
|
174
|
+
const { fromAddress, toAddress, amount, network, rpcUrl, tokenMint } = data;
|
|
148
175
|
|
|
149
176
|
if (!this.connector) {
|
|
150
177
|
throw new Error('SolanaAdapter:sendTransaction - no active connector');
|
|
@@ -184,12 +211,20 @@ export class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
184
211
|
// Create connection
|
|
185
212
|
const connection = new Connection(connectionRpcUrl, 'confirmed');
|
|
186
213
|
|
|
187
|
-
const transaction =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
214
|
+
const transaction = tokenMint
|
|
215
|
+
? await createSPLTokenTransaction({
|
|
216
|
+
connection,
|
|
217
|
+
fromAddress,
|
|
218
|
+
toAddress,
|
|
219
|
+
amount,
|
|
220
|
+
tokenMint
|
|
221
|
+
})
|
|
222
|
+
: await createSendTransaction({
|
|
223
|
+
connection,
|
|
224
|
+
fromAddress,
|
|
225
|
+
toAddress,
|
|
226
|
+
amount
|
|
227
|
+
});
|
|
193
228
|
|
|
194
229
|
// Sign the transaction
|
|
195
230
|
const signedTransaction = await this.signTransaction(transaction, network);
|
|
@@ -213,6 +248,39 @@ export class SolanaAdapter extends SolanaBaseAdapter {
|
|
|
213
248
|
}
|
|
214
249
|
}
|
|
215
250
|
|
|
251
|
+
override async signMessage(address: string, message: string, chainId?: string): Promise<string> {
|
|
252
|
+
try {
|
|
253
|
+
if (!this.connector) {
|
|
254
|
+
throw new Error('SolanaAdapter:signMessage - no active connector');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const provider = this.connector.getProvider('solana');
|
|
258
|
+
if (!provider) {
|
|
259
|
+
throw new Error('SolanaAdapter:signMessage - provider is undefined');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const chain = chainId ? `${this.getSupportedNamespace()}:${chainId}` : undefined;
|
|
263
|
+
|
|
264
|
+
const encodedMessage = new TextEncoder().encode(message);
|
|
265
|
+
const params = {
|
|
266
|
+
message: base58.encode(encodedMessage),
|
|
267
|
+
pubkey: address
|
|
268
|
+
// For Phantom, pubkey is not part of signMessage params directly with session
|
|
269
|
+
// For other wallets, it might be needed if they don't infer from session
|
|
270
|
+
};
|
|
271
|
+
const { signature } = (await provider.request(
|
|
272
|
+
{ method: 'solana_signMessage', params },
|
|
273
|
+
chain
|
|
274
|
+
)) as {
|
|
275
|
+
signature: string;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
return signature;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
216
284
|
async switchNetwork(network: AppKitNetwork): Promise<void> {
|
|
217
285
|
if (!this.connector) throw new Error('No active connector');
|
|
218
286
|
|
|
@@ -12,7 +12,10 @@ export class PhantomConnector extends DeeplinkConnector {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
override getWalletInfo(): WalletInfo {
|
|
15
|
-
return
|
|
15
|
+
return {
|
|
16
|
+
name: ConstantsUtil.PHANTOM_CUSTOM_WALLET.name,
|
|
17
|
+
type: 'external'
|
|
18
|
+
};
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
protected getBaseUrl(): string {
|
|
@@ -12,7 +12,10 @@ export class SolflareConnector extends DeeplinkConnector {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
override getWalletInfo(): WalletInfo {
|
|
15
|
-
return
|
|
15
|
+
return {
|
|
16
|
+
name: ConstantsUtil.SOLFLARE_CUSTOM_WALLET.name,
|
|
17
|
+
type: 'external'
|
|
18
|
+
};
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
protected getBaseUrl(): string {
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
WalletInfo
|
|
6
6
|
} from '@reown/appkit-common-react-native';
|
|
7
7
|
import type nacl from 'tweetnacl';
|
|
8
|
+
import type { Connection } from '@solana/web3.js';
|
|
8
9
|
|
|
9
10
|
// --- From helpers ---
|
|
10
11
|
|
|
@@ -16,6 +17,14 @@ export interface TokenInfo {
|
|
|
16
17
|
logoURI?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
export type SPLTokenTransactionArgs = {
|
|
21
|
+
connection: Connection;
|
|
22
|
+
fromAddress: string;
|
|
23
|
+
toAddress: string;
|
|
24
|
+
amount: number;
|
|
25
|
+
tokenMint: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
19
28
|
// --- From PhantomProvider ---
|
|
20
29
|
|
|
21
30
|
export type Cluster = 'mainnet-beta' | 'testnet' | 'devnet';
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TOKEN_2022_PROGRAM_ID,
|
|
3
|
+
TOKEN_PROGRAM_ID,
|
|
4
|
+
TokenAccountNotFoundError,
|
|
5
|
+
createAssociatedTokenAccountInstruction,
|
|
6
|
+
createTransferCheckedInstruction,
|
|
7
|
+
getAccount,
|
|
8
|
+
getAssociatedTokenAddressSync,
|
|
9
|
+
getMint
|
|
10
|
+
} from '@solana/spl-token';
|
|
11
|
+
import {
|
|
12
|
+
ComputeBudgetProgram,
|
|
13
|
+
Connection,
|
|
14
|
+
PublicKey,
|
|
15
|
+
Transaction,
|
|
16
|
+
type TransactionInstruction
|
|
17
|
+
} from '@solana/web3.js';
|
|
18
|
+
import type { SPLTokenTransactionArgs } from '../types';
|
|
19
|
+
|
|
20
|
+
const SPL_COMPUTE_BUDGET_CONSTANTS = {
|
|
21
|
+
UNIT_PRICE_MICRO_LAMPORTS: 1000000,
|
|
22
|
+
UNIT_LIMIT_WITH_ATA_CREATION: 400000
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
async function getMintOwnerProgramId(connection: Connection, mint: PublicKey) {
|
|
26
|
+
const info = await connection.getAccountInfo(mint);
|
|
27
|
+
|
|
28
|
+
if (!info) {
|
|
29
|
+
throw new Error('Mint account not found');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (info.owner.equals(TOKEN_PROGRAM_ID)) {
|
|
33
|
+
return TOKEN_PROGRAM_ID;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) {
|
|
37
|
+
return TOKEN_2022_PROGRAM_ID;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw new Error('Unknown mint owner program');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function createSPLTokenTransaction({
|
|
44
|
+
fromAddress,
|
|
45
|
+
toAddress,
|
|
46
|
+
amount,
|
|
47
|
+
tokenMint,
|
|
48
|
+
connection
|
|
49
|
+
}: SPLTokenTransactionArgs): Promise<Transaction> {
|
|
50
|
+
if (!fromAddress) {
|
|
51
|
+
throw new Error('No public key found');
|
|
52
|
+
}
|
|
53
|
+
if (amount <= 0) {
|
|
54
|
+
throw new Error('Amount must be greater than 0');
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const fromPubkey = new PublicKey(fromAddress);
|
|
58
|
+
const toPubkey = new PublicKey(toAddress);
|
|
59
|
+
const mintPubkey = new PublicKey(tokenMint);
|
|
60
|
+
|
|
61
|
+
const programId = await getMintOwnerProgramId(connection, mintPubkey);
|
|
62
|
+
|
|
63
|
+
const mintInfo = await getMint(connection, mintPubkey, undefined, programId);
|
|
64
|
+
const decimals = mintInfo.decimals;
|
|
65
|
+
if (decimals < 0) {
|
|
66
|
+
throw new Error('Invalid token decimals');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const tokenAmount = Math.floor(amount * 10 ** decimals);
|
|
70
|
+
|
|
71
|
+
const fromTokenAccount = getAssociatedTokenAddressSync(
|
|
72
|
+
mintPubkey,
|
|
73
|
+
fromPubkey,
|
|
74
|
+
false,
|
|
75
|
+
programId
|
|
76
|
+
);
|
|
77
|
+
const toTokenAccount = getAssociatedTokenAddressSync(mintPubkey, toPubkey, false, programId);
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const fromAccount = await getAccount(connection, fromTokenAccount, undefined, programId);
|
|
81
|
+
if (fromAccount.amount < BigInt(tokenAmount)) {
|
|
82
|
+
throw new Error('Insufficient token balance');
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (error instanceof TokenAccountNotFoundError) {
|
|
86
|
+
throw new Error('Sender does not have a token account for this mint');
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let shouldCreateATA = false;
|
|
92
|
+
try {
|
|
93
|
+
await getAccount(connection, toTokenAccount, undefined, programId);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (error instanceof TokenAccountNotFoundError) {
|
|
96
|
+
shouldCreateATA = true;
|
|
97
|
+
} else {
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const instructions: TransactionInstruction[] = [];
|
|
103
|
+
|
|
104
|
+
if (shouldCreateATA) {
|
|
105
|
+
instructions.push(
|
|
106
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
107
|
+
microLamports: SPL_COMPUTE_BUDGET_CONSTANTS.UNIT_PRICE_MICRO_LAMPORTS
|
|
108
|
+
}),
|
|
109
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
110
|
+
units: SPL_COMPUTE_BUDGET_CONSTANTS.UNIT_LIMIT_WITH_ATA_CREATION
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
instructions.push(
|
|
115
|
+
createAssociatedTokenAccountInstruction(
|
|
116
|
+
fromPubkey,
|
|
117
|
+
toTokenAccount,
|
|
118
|
+
toPubkey,
|
|
119
|
+
mintPubkey,
|
|
120
|
+
programId
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
instructions.push(
|
|
126
|
+
createTransferCheckedInstruction(
|
|
127
|
+
fromTokenAccount,
|
|
128
|
+
mintPubkey,
|
|
129
|
+
toTokenAccount,
|
|
130
|
+
fromPubkey,
|
|
131
|
+
tokenAmount,
|
|
132
|
+
decimals,
|
|
133
|
+
[],
|
|
134
|
+
programId
|
|
135
|
+
)
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
139
|
+
|
|
140
|
+
return new Transaction({
|
|
141
|
+
feePayer: fromPubkey,
|
|
142
|
+
blockhash,
|
|
143
|
+
lastValidBlockHeight
|
|
144
|
+
}).add(...instructions);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`Failed to create SPL token transaction: ${
|
|
148
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
149
|
+
}`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|