@reown/appkit-solana-react-native 0.0.1 → 2.0.0-alpha.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.
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.SolanaAdapter = void 0;
7
7
  var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
8
- var _web = require("@solana/web3.js");
8
+ var _helpers = require("./helpers");
9
9
  class SolanaAdapter extends _appkitCommonReactNative.SolanaBaseAdapter {
10
10
  static supportedNamespace = 'solana';
11
11
  constructor(configParams) {
@@ -17,26 +17,41 @@ class SolanaAdapter extends _appkitCommonReactNative.SolanaBaseAdapter {
17
17
  async getBalance(params) {
18
18
  const {
19
19
  network,
20
- address
20
+ address,
21
+ tokens
21
22
  } = params;
22
23
  if (!this.connector) throw new Error('No active connector');
23
24
  if (!network) throw new Error('No network provided');
24
25
  const balanceAddress = address || this.getAccounts()?.find(account => account.includes(network.id.toString()));
25
26
  if (!balanceAddress) {
26
- return Promise.resolve({
27
+ return {
27
28
  amount: '0.00',
28
29
  symbol: 'SOL'
29
- });
30
+ };
30
31
  }
31
32
  try {
32
- const connection = new _web.Connection(network?.rpcUrls?.default?.http?.[0]); //TODO: check connection settings
33
- const balanceAmount = await connection.getBalance(new _web.PublicKey(balanceAddress.split(':')[2]));
34
- const formattedBalance = (balanceAmount / 1000000000).toString(); //TODO: add util with LAMPORTS_PER_SOL
35
-
36
- const balance = {
37
- amount: formattedBalance,
38
- symbol: network?.nativeCurrency.symbol || 'SOL'
39
- };
33
+ const rpcUrl = network.rpcUrls?.default?.http?.[0];
34
+ if (!rpcUrl) throw new Error('No RPC URL available');
35
+ const base58Address = balanceAddress.split(':')[2];
36
+ if (!base58Address) throw new Error('Invalid balance address');
37
+ const token = network?.caipNetworkId && tokens?.[network.caipNetworkId]?.address;
38
+ let balance;
39
+ if (token) {
40
+ const {
41
+ amount,
42
+ symbol
43
+ } = await (0, _helpers.getSolanaTokenBalance)(rpcUrl, base58Address, token);
44
+ balance = {
45
+ amount,
46
+ symbol
47
+ };
48
+ } else {
49
+ const amount = await (0, _helpers.getSolanaNativeBalance)(rpcUrl, base58Address);
50
+ balance = {
51
+ amount: amount.toString(),
52
+ symbol: 'SOL'
53
+ };
54
+ }
40
55
  this.emit('balanceChanged', {
41
56
  namespace: this.getSupportedNamespace(),
42
57
  address: balanceAddress,
@@ -67,16 +82,8 @@ class SolanaAdapter extends _appkitCommonReactNative.SolanaBaseAdapter {
67
82
  return namespaces[this.getSupportedNamespace()]?.accounts;
68
83
  }
69
84
  disconnect() {
70
- if (!this.connector) throw new Error('SolanaAdapter:disconnect - No active connector');
71
- return this.connector.disconnect();
72
- }
73
- async request(method, params) {
74
85
  if (!this.connector) throw new Error('No active connector');
75
- const provider = this.connector.getProvider();
76
- return provider.request({
77
- method,
78
- params
79
- });
86
+ return this.connector.disconnect();
80
87
  }
81
88
  getSupportedNamespace() {
82
89
  return SolanaAdapter.supportedNamespace;
@@ -1 +1 @@
1
- {"version":3,"names":["_appkitCommonReactNative","require","_web","SolanaAdapter","SolanaBaseAdapter","supportedNamespace","constructor","configParams","projectId","getBalance","params","network","address","connector","Error","balanceAddress","getAccounts","find","account","includes","id","toString","Promise","resolve","amount","symbol","connection","Connection","rpcUrls","default","http","balanceAmount","PublicKey","split","formattedBalance","balance","nativeCurrency","emit","namespace","getSupportedNamespace","error","switchNetwork","provider","getProvider","switchError","namespaces","getNamespaces","accounts","disconnect","request","method","exports"],"sourceRoot":"../../src","sources":["adapter.ts"],"mappings":"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"}
1
+ {"version":3,"names":["_appkitCommonReactNative","require","_helpers","SolanaAdapter","SolanaBaseAdapter","supportedNamespace","constructor","configParams","projectId","getBalance","params","network","address","tokens","connector","Error","balanceAddress","getAccounts","find","account","includes","id","toString","amount","symbol","rpcUrl","rpcUrls","default","http","base58Address","split","token","caipNetworkId","balance","getSolanaTokenBalance","getSolanaNativeBalance","emit","namespace","getSupportedNamespace","error","switchNetwork","provider","getProvider","switchError","namespaces","getNamespaces","accounts","disconnect","exports"],"sourceRoot":"../../src","sources":["adapter.ts"],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getSolanaNativeBalance = getSolanaNativeBalance;
7
+ exports.getSolanaTokenBalance = getSolanaTokenBalance;
8
+ exports.getSolanaTokenMetadata = getSolanaTokenMetadata;
9
+ exports.isSolanaAddress = isSolanaAddress;
10
+ /**
11
+ * Validates if the given string is a Solana address.
12
+ * @param address The string to validate.
13
+ * @returns True if the address is valid, false otherwise.
14
+ */
15
+ function isSolanaAddress(address) {
16
+ const solanaAddressRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
17
+ return solanaAddressRegex.test(address);
18
+ }
19
+
20
+ /**
21
+ * Helper to fetch SOL balance using JSON-RPC
22
+ * @param rpcUrl Solana RPC endpoint
23
+ * @param address Solana public address (base58)
24
+ */
25
+ async function getSolanaNativeBalance(rpcUrl, address) {
26
+ if (!isSolanaAddress(address)) {
27
+ throw new Error('Invalid Solana address format');
28
+ }
29
+ const response = await fetch(rpcUrl, {
30
+ method: 'POST',
31
+ headers: {
32
+ 'Content-Type': 'application/json'
33
+ },
34
+ body: JSON.stringify({
35
+ jsonrpc: '2.0',
36
+ id: 1,
37
+ method: 'getBalance',
38
+ params: [address]
39
+ })
40
+ });
41
+ const json = await response.json();
42
+ if (json.error) throw new Error(json.error.message);
43
+ return json.result.value / 1000000000; // Convert lamports to SOL
44
+ }
45
+
46
+ let tokenCache = {};
47
+ /**
48
+ * Fetch metadata for a Solana SPL token using the Jupiter token list.
49
+ * @param mint - The token's mint address
50
+ * @returns TokenInfo if found, or undefined
51
+ */
52
+ async function getSolanaTokenMetadata(mint) {
53
+ // Return from cache if available
54
+ if (tokenCache[mint]) return tokenCache[mint];
55
+ try {
56
+ const res = await fetch('https://token.jup.ag/all');
57
+ const list = await res.json();
58
+ for (const token of list) {
59
+ tokenCache[token.address] = token;
60
+ }
61
+ return tokenCache[mint];
62
+ } catch (error) {
63
+ return undefined;
64
+ }
65
+ }
66
+ async function getSolanaTokenBalance(rpcUrl, address, tokenAddress) {
67
+ if (!isSolanaAddress(address)) {
68
+ throw new Error('Invalid Solana address format');
69
+ }
70
+ const token = await getSolanaTokenMetadata(tokenAddress);
71
+ const response = await fetch(rpcUrl, {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json'
75
+ },
76
+ body: JSON.stringify({
77
+ jsonrpc: '2.0',
78
+ id: 1,
79
+ method: 'getTokenAccountsByOwner',
80
+ params: [address, {
81
+ mint: tokenAddress
82
+ }, {
83
+ encoding: 'jsonParsed'
84
+ }]
85
+ })
86
+ });
87
+ const result = await response.json();
88
+ const balance = result.result.value[0]?.account?.data?.parsed?.info?.tokenAmount?.uiAmount;
89
+ return {
90
+ amount: balance?.toString() ?? '0',
91
+ symbol: token?.symbol ?? 'SOL'
92
+ };
93
+ }
94
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isSolanaAddress","address","solanaAddressRegex","test","getSolanaNativeBalance","rpcUrl","Error","response","fetch","method","headers","body","JSON","stringify","jsonrpc","id","params","json","error","message","result","value","tokenCache","getSolanaTokenMetadata","mint","res","list","token","undefined","getSolanaTokenBalance","tokenAddress","encoding","balance","account","data","parsed","info","tokenAmount","uiAmount","amount","toString","symbol"],"sourceRoot":"../../src","sources":["helpers.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { SolanaBaseAdapter } from '@reown/appkit-common-react-native';
2
- import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { getSolanaNativeBalance, getSolanaTokenBalance } from './helpers';
3
3
  export class SolanaAdapter extends SolanaBaseAdapter {
4
4
  static supportedNamespace = 'solana';
5
5
  constructor(configParams) {
@@ -11,26 +11,41 @@ export class SolanaAdapter extends SolanaBaseAdapter {
11
11
  async getBalance(params) {
12
12
  const {
13
13
  network,
14
- address
14
+ address,
15
+ tokens
15
16
  } = params;
16
17
  if (!this.connector) throw new Error('No active connector');
17
18
  if (!network) throw new Error('No network provided');
18
19
  const balanceAddress = address || this.getAccounts()?.find(account => account.includes(network.id.toString()));
19
20
  if (!balanceAddress) {
20
- return Promise.resolve({
21
+ return {
21
22
  amount: '0.00',
22
23
  symbol: 'SOL'
23
- });
24
+ };
24
25
  }
25
26
  try {
26
- const connection = new Connection(network?.rpcUrls?.default?.http?.[0]); //TODO: check connection settings
27
- const balanceAmount = await connection.getBalance(new PublicKey(balanceAddress.split(':')[2]));
28
- const formattedBalance = (balanceAmount / 1000000000).toString(); //TODO: add util with LAMPORTS_PER_SOL
29
-
30
- const balance = {
31
- amount: formattedBalance,
32
- symbol: network?.nativeCurrency.symbol || 'SOL'
33
- };
27
+ const rpcUrl = network.rpcUrls?.default?.http?.[0];
28
+ if (!rpcUrl) throw new Error('No RPC URL available');
29
+ const base58Address = balanceAddress.split(':')[2];
30
+ if (!base58Address) throw new Error('Invalid balance address');
31
+ const token = network?.caipNetworkId && tokens?.[network.caipNetworkId]?.address;
32
+ let balance;
33
+ if (token) {
34
+ const {
35
+ amount,
36
+ symbol
37
+ } = await getSolanaTokenBalance(rpcUrl, base58Address, token);
38
+ balance = {
39
+ amount,
40
+ symbol
41
+ };
42
+ } else {
43
+ const amount = await getSolanaNativeBalance(rpcUrl, base58Address);
44
+ balance = {
45
+ amount: amount.toString(),
46
+ symbol: 'SOL'
47
+ };
48
+ }
34
49
  this.emit('balanceChanged', {
35
50
  namespace: this.getSupportedNamespace(),
36
51
  address: balanceAddress,
@@ -61,16 +76,8 @@ export class SolanaAdapter extends SolanaBaseAdapter {
61
76
  return namespaces[this.getSupportedNamespace()]?.accounts;
62
77
  }
63
78
  disconnect() {
64
- if (!this.connector) throw new Error('SolanaAdapter:disconnect - No active connector');
65
- return this.connector.disconnect();
66
- }
67
- async request(method, params) {
68
79
  if (!this.connector) throw new Error('No active connector');
69
- const provider = this.connector.getProvider();
70
- return provider.request({
71
- method,
72
- params
73
- });
80
+ return this.connector.disconnect();
74
81
  }
75
82
  getSupportedNamespace() {
76
83
  return SolanaAdapter.supportedNamespace;
@@ -1 +1 @@
1
- {"version":3,"names":["SolanaBaseAdapter","Connection","PublicKey","SolanaAdapter","supportedNamespace","constructor","configParams","projectId","getBalance","params","network","address","connector","Error","balanceAddress","getAccounts","find","account","includes","id","toString","Promise","resolve","amount","symbol","connection","rpcUrls","default","http","balanceAmount","split","formattedBalance","balance","nativeCurrency","emit","namespace","getSupportedNamespace","error","switchNetwork","provider","getProvider","switchError","namespaces","getNamespaces","accounts","disconnect","request","method"],"sourceRoot":"../../src","sources":["adapter.ts"],"mappings":"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"}
1
+ {"version":3,"names":["SolanaBaseAdapter","getSolanaNativeBalance","getSolanaTokenBalance","SolanaAdapter","supportedNamespace","constructor","configParams","projectId","getBalance","params","network","address","tokens","connector","Error","balanceAddress","getAccounts","find","account","includes","id","toString","amount","symbol","rpcUrl","rpcUrls","default","http","base58Address","split","token","caipNetworkId","balance","emit","namespace","getSupportedNamespace","error","switchNetwork","provider","getProvider","switchError","namespaces","getNamespaces","accounts","disconnect"],"sourceRoot":"../../src","sources":["adapter.ts"],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Validates if the given string is a Solana address.
3
+ * @param address The string to validate.
4
+ * @returns True if the address is valid, false otherwise.
5
+ */
6
+ export function isSolanaAddress(address) {
7
+ const solanaAddressRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
8
+ return solanaAddressRegex.test(address);
9
+ }
10
+
11
+ /**
12
+ * Helper to fetch SOL balance using JSON-RPC
13
+ * @param rpcUrl Solana RPC endpoint
14
+ * @param address Solana public address (base58)
15
+ */
16
+ export async function getSolanaNativeBalance(rpcUrl, address) {
17
+ if (!isSolanaAddress(address)) {
18
+ throw new Error('Invalid Solana address format');
19
+ }
20
+ const response = await fetch(rpcUrl, {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json'
24
+ },
25
+ body: JSON.stringify({
26
+ jsonrpc: '2.0',
27
+ id: 1,
28
+ method: 'getBalance',
29
+ params: [address]
30
+ })
31
+ });
32
+ const json = await response.json();
33
+ if (json.error) throw new Error(json.error.message);
34
+ return json.result.value / 1000000000; // Convert lamports to SOL
35
+ }
36
+
37
+ let tokenCache = {};
38
+ /**
39
+ * Fetch metadata for a Solana SPL token using the Jupiter token list.
40
+ * @param mint - The token's mint address
41
+ * @returns TokenInfo if found, or undefined
42
+ */
43
+ export async function getSolanaTokenMetadata(mint) {
44
+ // Return from cache if available
45
+ if (tokenCache[mint]) return tokenCache[mint];
46
+ try {
47
+ const res = await fetch('https://token.jup.ag/all');
48
+ const list = await res.json();
49
+ for (const token of list) {
50
+ tokenCache[token.address] = token;
51
+ }
52
+ return tokenCache[mint];
53
+ } catch (error) {
54
+ return undefined;
55
+ }
56
+ }
57
+ export async function getSolanaTokenBalance(rpcUrl, address, tokenAddress) {
58
+ if (!isSolanaAddress(address)) {
59
+ throw new Error('Invalid Solana address format');
60
+ }
61
+ const token = await getSolanaTokenMetadata(tokenAddress);
62
+ const response = await fetch(rpcUrl, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Content-Type': 'application/json'
66
+ },
67
+ body: JSON.stringify({
68
+ jsonrpc: '2.0',
69
+ id: 1,
70
+ method: 'getTokenAccountsByOwner',
71
+ params: [address, {
72
+ mint: tokenAddress
73
+ }, {
74
+ encoding: 'jsonParsed'
75
+ }]
76
+ })
77
+ });
78
+ const result = await response.json();
79
+ const balance = result.result.value[0]?.account?.data?.parsed?.info?.tokenAmount?.uiAmount;
80
+ return {
81
+ amount: balance?.toString() ?? '0',
82
+ symbol: token?.symbol ?? 'SOL'
83
+ };
84
+ }
85
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isSolanaAddress","address","solanaAddressRegex","test","getSolanaNativeBalance","rpcUrl","Error","response","fetch","method","headers","body","JSON","stringify","jsonrpc","id","params","json","error","message","result","value","tokenCache","getSolanaTokenMetadata","mint","res","list","token","undefined","getSolanaTokenBalance","tokenAddress","encoding","balance","account","data","parsed","info","tokenAmount","uiAmount","amount","toString","symbol"],"sourceRoot":"../../src","sources":["helpers.ts"],"mappings":"AAQA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,eAAeA,CAACC,OAAe,EAAW;EACxD,MAAMC,kBAAkB,GAAG,+BAA+B;EAE1D,OAAOA,kBAAkB,CAACC,IAAI,CAACF,OAAO,CAAC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeG,sBAAsBA,CAACC,MAAc,EAAEJ,OAAe,EAAmB;EAC7F,IAAI,CAACD,eAAe,CAACC,OAAO,CAAC,EAAE;IAC7B,MAAM,IAAIK,KAAK,CAAC,+BAA+B,CAAC;EAClD;EAEA,MAAMC,QAAQ,GAAG,MAAMC,KAAK,CAACH,MAAM,EAAE;IACnCI,MAAM,EAAE,MAAM;IACdC,OAAO,EAAE;MAAE,cAAc,EAAE;IAAmB,CAAC;IAC/CC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAAC;MACnBC,OAAO,EAAE,KAAK;MACdC,EAAE,EAAE,CAAC;MACLN,MAAM,EAAE,YAAY;MACpBO,MAAM,EAAE,CAACf,OAAO;IAClB,CAAC;EACH,CAAC,CAAC;EAEF,MAAMgB,IAAI,GAAI,MAAMV,QAAQ,CAACU,IAAI,CAAC,CAGjC;EACD,IAAIA,IAAI,CAACC,KAAK,EAAE,MAAM,IAAIZ,KAAK,CAACW,IAAI,CAACC,KAAK,CAACC,OAAO,CAAC;EAEnD,OAAOF,IAAI,CAACG,MAAM,CAACC,KAAK,GAAG,UAAU,CAAC,CAAC;AACzC;;AAEA,IAAIC,UAAqC,GAAG,CAAC,CAAC;AAC9C;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,sBAAsBA,CAACC,IAAY,EAAkC;EACzF;EACA,IAAIF,UAAU,CAACE,IAAI,CAAC,EAAE,OAAOF,UAAU,CAACE,IAAI,CAAC;EAE7C,IAAI;IACF,MAAMC,GAAG,GAAG,MAAMjB,KAAK,CAAC,0BAA0B,CAAC;IACnD,MAAMkB,IAAiB,GAAG,MAAMD,GAAG,CAACR,IAAI,CAAC,CAAC;IAE1C,KAAK,MAAMU,KAAK,IAAID,IAAI,EAAE;MACxBJ,UAAU,CAACK,KAAK,CAAC1B,OAAO,CAAC,GAAG0B,KAAK;IACnC;IAEA,OAAOL,UAAU,CAACE,IAAI,CAAC;EACzB,CAAC,CAAC,OAAON,KAAK,EAAE;IACd,OAAOU,SAAS;EAClB;AACF;AAEA,OAAO,eAAeC,qBAAqBA,CACzCxB,MAAc,EACdJ,OAAe,EACf6B,YAAoB,EACyB;EAC7C,IAAI,CAAC9B,eAAe,CAACC,OAAO,CAAC,EAAE;IAC7B,MAAM,IAAIK,KAAK,CAAC,+BAA+B,CAAC;EAClD;EAEA,MAAMqB,KAAK,GAAG,MAAMJ,sBAAsB,CAACO,YAAY,CAAC;EAExD,MAAMvB,QAAQ,GAAG,MAAMC,KAAK,CAACH,MAAM,EAAE;IACnCI,MAAM,EAAE,MAAM;IACdC,OAAO,EAAE;MAAE,cAAc,EAAE;IAAmB,CAAC;IAC/CC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAAC;MACnBC,OAAO,EAAE,KAAK;MACdC,EAAE,EAAE,CAAC;MACLN,MAAM,EAAE,yBAAyB;MACjCO,MAAM,EAAE,CAACf,OAAO,EAAE;QAAEuB,IAAI,EAAEM;MAAa,CAAC,EAAE;QAAEC,QAAQ,EAAE;MAAa,CAAC;IACtE,CAAC;EACH,CAAC,CAAC;EAEF,MAAMX,MAAM,GAAG,MAAMb,QAAQ,CAACU,IAAI,CAAC,CAAC;EACpC,MAAMe,OAAO,GAAGZ,MAAM,CAACA,MAAM,CAACC,KAAK,CAAC,CAAC,CAAC,EAAEY,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,IAAI,EAAEC,WAAW,EAAEC,QAAQ;EAE1F,OAAO;IAAEC,MAAM,EAAEP,OAAO,EAAEQ,QAAQ,CAAC,CAAC,IAAI,GAAG;IAAEC,MAAM,EAAEd,KAAK,EAAEc,MAAM,IAAI;EAAM,CAAC;AAC/E"}
@@ -8,7 +8,6 @@ export declare class SolanaAdapter extends SolanaBaseAdapter {
8
8
  switchNetwork(network: AppKitNetwork): Promise<void>;
9
9
  getAccounts(): CaipAddress[] | undefined;
10
10
  disconnect(): Promise<void>;
11
- request(method: string, params?: any[]): Promise<unknown>;
12
11
  getSupportedNamespace(): ChainNamespace;
13
12
  }
14
13
  //# sourceMappingURL=adapter.d.ts.map
@@ -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;AAG3C,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA4B;gBAEjD,YAAY,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAOzC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAqCjE,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1D,WAAW,IAAI,WAAW,EAAE,GAAG,SAAS;IAOxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE;IAO5C,qBAAqB,IAAI,cAAc;CAGxC"}
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;AAG3C,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA4B;gBAEjD,YAAY,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAOzC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkDjE,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"}
@@ -0,0 +1,30 @@
1
+ export interface TokenInfo {
2
+ address: string;
3
+ symbol: string;
4
+ name: string;
5
+ decimals: number;
6
+ logoURI?: string;
7
+ }
8
+ /**
9
+ * Validates if the given string is a Solana address.
10
+ * @param address The string to validate.
11
+ * @returns True if the address is valid, false otherwise.
12
+ */
13
+ export declare function isSolanaAddress(address: string): boolean;
14
+ /**
15
+ * Helper to fetch SOL balance using JSON-RPC
16
+ * @param rpcUrl Solana RPC endpoint
17
+ * @param address Solana public address (base58)
18
+ */
19
+ export declare function getSolanaNativeBalance(rpcUrl: string, address: string): Promise<number>;
20
+ /**
21
+ * Fetch metadata for a Solana SPL token using the Jupiter token list.
22
+ * @param mint - The token's mint address
23
+ * @returns TokenInfo if found, or undefined
24
+ */
25
+ export declare function getSolanaTokenMetadata(mint: string): Promise<TokenInfo | undefined>;
26
+ export declare function getSolanaTokenBalance(rpcUrl: string, address: string, tokenAddress: string): Promise<{
27
+ amount: string;
28
+ symbol: string;
29
+ }>;
30
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAIxD;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB7F;AAGD;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAgBzF;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB7C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reown/appkit-solana-react-native",
3
- "version": "0.0.1",
3
+ "version": "2.0.0-alpha.0",
4
4
  "main": "lib/commonjs/index.js",
5
5
  "types": "lib/typescript/index.d.ts",
6
6
  "module": "lib/module/index.js",
@@ -38,15 +38,7 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "@reown/appkit-common-react-native": "1.2.3",
42
- "@solana/web3.js": "1.98.2"
43
- },
44
- "peerDependencies": {
45
- "@solana/web3.js": ">=1.90.0",
46
- "bs58": ">=6.0.0"
47
- },
48
- "devDependencies": {
49
- "@solana/web3.js": "1.98.2"
41
+ "@reown/appkit-common-react-native": "2.0.0-alpha.0"
50
42
  },
51
43
  "react-native": "src/index.tsx"
52
- }
44
+ }
package/src/adapter.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  type GetBalanceParams,
7
7
  type GetBalanceResponse
8
8
  } from '@reown/appkit-common-react-native';
9
- import { Connection, PublicKey } from '@solana/web3.js';
9
+ import { getSolanaNativeBalance, getSolanaTokenBalance } from './helpers';
10
10
 
11
11
  export class SolanaAdapter extends SolanaBaseAdapter {
12
12
  private static supportedNamespace: ChainNamespace = 'solana';
@@ -19,7 +19,7 @@ export class SolanaAdapter extends SolanaBaseAdapter {
19
19
  }
20
20
 
21
21
  async getBalance(params: GetBalanceParams): Promise<GetBalanceResponse> {
22
- const { network, address } = params;
22
+ const { network, address, tokens } = params;
23
23
 
24
24
  if (!this.connector) throw new Error('No active connector');
25
25
  if (!network) throw new Error('No network provided');
@@ -28,20 +28,33 @@ export class SolanaAdapter extends SolanaBaseAdapter {
28
28
  address || this.getAccounts()?.find(account => account.includes(network.id.toString()));
29
29
 
30
30
  if (!balanceAddress) {
31
- return Promise.resolve({ amount: '0.00', symbol: 'SOL' });
31
+ return { amount: '0.00', symbol: 'SOL' };
32
32
  }
33
33
 
34
34
  try {
35
- const connection = new Connection(network?.rpcUrls?.default?.http?.[0] as string); //TODO: check connection settings
36
- const balanceAmount = await connection.getBalance(
37
- new PublicKey(balanceAddress.split(':')[2] as string)
38
- );
39
- const formattedBalance = (balanceAmount / 1000000000).toString(); //TODO: add util with LAMPORTS_PER_SOL
40
-
41
- const balance = {
42
- amount: formattedBalance,
43
- symbol: network?.nativeCurrency.symbol || 'SOL'
44
- };
35
+ const rpcUrl = network.rpcUrls?.default?.http?.[0];
36
+ if (!rpcUrl) throw new Error('No RPC URL available');
37
+
38
+ const base58Address = balanceAddress.split(':')[2];
39
+
40
+ if (!base58Address) throw new Error('Invalid balance address');
41
+
42
+ const token = network?.caipNetworkId && tokens?.[network.caipNetworkId]?.address;
43
+ let balance;
44
+
45
+ if (token) {
46
+ const { amount, symbol } = await getSolanaTokenBalance(rpcUrl, base58Address, token);
47
+ balance = {
48
+ amount,
49
+ symbol
50
+ };
51
+ } else {
52
+ const amount = await getSolanaNativeBalance(rpcUrl, base58Address);
53
+ balance = {
54
+ amount: amount.toString(),
55
+ symbol: 'SOL'
56
+ };
57
+ }
45
58
 
46
59
  this.emit('balanceChanged', {
47
60
  namespace: this.getSupportedNamespace(),
@@ -78,16 +91,9 @@ export class SolanaAdapter extends SolanaBaseAdapter {
78
91
  }
79
92
 
80
93
  disconnect(): Promise<void> {
81
- if (!this.connector) throw new Error('SolanaAdapter:disconnect - No active connector');
82
-
83
- return this.connector.disconnect();
84
- }
85
-
86
- async request(method: string, params?: any[]) {
87
94
  if (!this.connector) throw new Error('No active connector');
88
- const provider = this.connector.getProvider();
89
95
 
90
- return provider.request({ method, params });
96
+ return this.connector.disconnect();
91
97
  }
92
98
 
93
99
  getSupportedNamespace(): ChainNamespace {
package/src/helpers.ts ADDED
@@ -0,0 +1,100 @@
1
+ export interface TokenInfo {
2
+ address: string;
3
+ symbol: string;
4
+ name: string;
5
+ decimals: number;
6
+ logoURI?: string;
7
+ }
8
+
9
+ /**
10
+ * Validates if the given string is a Solana address.
11
+ * @param address The string to validate.
12
+ * @returns True if the address is valid, false otherwise.
13
+ */
14
+ export function isSolanaAddress(address: string): boolean {
15
+ const solanaAddressRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
16
+
17
+ return solanaAddressRegex.test(address);
18
+ }
19
+
20
+ /**
21
+ * Helper to fetch SOL balance using JSON-RPC
22
+ * @param rpcUrl Solana RPC endpoint
23
+ * @param address Solana public address (base58)
24
+ */
25
+ export async function getSolanaNativeBalance(rpcUrl: string, address: string): Promise<number> {
26
+ if (!isSolanaAddress(address)) {
27
+ throw new Error('Invalid Solana address format');
28
+ }
29
+
30
+ const response = await fetch(rpcUrl, {
31
+ method: 'POST',
32
+ headers: { 'Content-Type': 'application/json' },
33
+ body: JSON.stringify({
34
+ jsonrpc: '2.0',
35
+ id: 1,
36
+ method: 'getBalance',
37
+ params: [address]
38
+ })
39
+ });
40
+
41
+ const json = (await response.json()) as {
42
+ result: { value: number };
43
+ error?: { message: string };
44
+ };
45
+ if (json.error) throw new Error(json.error.message);
46
+
47
+ return json.result.value / 1000000000; // Convert lamports to SOL
48
+ }
49
+
50
+ let tokenCache: Record<string, TokenInfo> = {};
51
+ /**
52
+ * Fetch metadata for a Solana SPL token using the Jupiter token list.
53
+ * @param mint - The token's mint address
54
+ * @returns TokenInfo if found, or undefined
55
+ */
56
+ export async function getSolanaTokenMetadata(mint: string): Promise<TokenInfo | undefined> {
57
+ // Return from cache if available
58
+ if (tokenCache[mint]) return tokenCache[mint];
59
+
60
+ try {
61
+ const res = await fetch('https://token.jup.ag/all');
62
+ const list: TokenInfo[] = await res.json();
63
+
64
+ for (const token of list) {
65
+ tokenCache[token.address] = token;
66
+ }
67
+
68
+ return tokenCache[mint];
69
+ } catch (error) {
70
+ return undefined;
71
+ }
72
+ }
73
+
74
+ export async function getSolanaTokenBalance(
75
+ rpcUrl: string,
76
+ address: string,
77
+ tokenAddress: string
78
+ ): Promise<{ amount: string; symbol: string }> {
79
+ if (!isSolanaAddress(address)) {
80
+ throw new Error('Invalid Solana address format');
81
+ }
82
+
83
+ const token = await getSolanaTokenMetadata(tokenAddress);
84
+
85
+ const response = await fetch(rpcUrl, {
86
+ method: 'POST',
87
+ headers: { 'Content-Type': 'application/json' },
88
+ body: JSON.stringify({
89
+ jsonrpc: '2.0',
90
+ id: 1,
91
+ method: 'getTokenAccountsByOwner',
92
+ params: [address, { mint: tokenAddress }, { encoding: 'jsonParsed' }]
93
+ })
94
+ });
95
+
96
+ const result = await response.json();
97
+ const balance = result.result.value[0]?.account?.data?.parsed?.info?.tokenAmount?.uiAmount;
98
+
99
+ return { amount: balance?.toString() ?? '0', symbol: token?.symbol ?? 'SOL' };
100
+ }