@reown/appkit-solana-react-native 2.0.0-alpha.1 → 2.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/commonjs/adapter.js +121 -3
  2. package/lib/commonjs/adapter.js.map +1 -1
  3. package/lib/commonjs/connectors/PhantomConnector.js +28 -24
  4. package/lib/commonjs/connectors/PhantomConnector.js.map +1 -1
  5. package/lib/commonjs/helpers.js +0 -1
  6. package/lib/commonjs/helpers.js.map +1 -1
  7. package/lib/commonjs/index.js +1 -1
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/package.json +1 -0
  10. package/lib/commonjs/providers/PhantomProvider.js +124 -84
  11. package/lib/commonjs/providers/PhantomProvider.js.map +1 -1
  12. package/lib/commonjs/types.js.map +1 -1
  13. package/lib/commonjs/utils/createSendTransaction.js +44 -0
  14. package/lib/commonjs/utils/createSendTransaction.js.map +1 -0
  15. package/lib/module/adapter.js +122 -3
  16. package/lib/module/adapter.js.map +1 -1
  17. package/lib/module/connectors/PhantomConnector.js +31 -25
  18. package/lib/module/connectors/PhantomConnector.js.map +1 -1
  19. package/lib/module/helpers.js +2 -1
  20. package/lib/module/helpers.js.map +1 -1
  21. package/lib/module/index.js +6 -4
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/module/providers/PhantomProvider.js +126 -84
  24. package/lib/module/providers/PhantomProvider.js.map +1 -1
  25. package/lib/module/types.js +2 -0
  26. package/lib/module/types.js.map +1 -1
  27. package/lib/module/utils/createSendTransaction.js +41 -0
  28. package/lib/module/utils/createSendTransaction.js.map +1 -0
  29. package/lib/typescript/adapter.d.ts +11 -3
  30. package/lib/typescript/adapter.d.ts.map +1 -1
  31. package/lib/typescript/connectors/PhantomConnector.d.ts +2 -1
  32. package/lib/typescript/connectors/PhantomConnector.d.ts.map +1 -1
  33. package/lib/typescript/index.d.ts +2 -2
  34. package/lib/typescript/index.d.ts.map +1 -1
  35. package/lib/typescript/providers/PhantomProvider.d.ts +14 -0
  36. package/lib/typescript/providers/PhantomProvider.d.ts.map +1 -1
  37. package/lib/typescript/utils/createSendTransaction.d.ts +10 -0
  38. package/lib/typescript/utils/createSendTransaction.d.ts.map +1 -0
  39. package/package.json +9 -3
  40. package/src/adapter.ts +152 -3
  41. package/src/connectors/PhantomConnector.ts +39 -38
  42. package/src/index.ts +4 -4
  43. package/src/providers/PhantomProvider.ts +165 -113
  44. package/src/utils/createSendTransaction.ts +57 -0
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ import { ComputeBudgetProgram, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
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
+ };
15
+ export async function createSendTransaction({
16
+ fromAddress,
17
+ toAddress,
18
+ value,
19
+ connection
20
+ }) {
21
+ const fromPubkey = new PublicKey(fromAddress);
22
+ const toPubkey = new PublicKey(toAddress);
23
+ const lamports = Math.floor(value * LAMPORTS_PER_SOL);
24
+ const {
25
+ blockhash
26
+ } = await connection.getLatestBlockhash();
27
+ const instructions = [ComputeBudgetProgram.setComputeUnitPrice({
28
+ microLamports: COMPUTE_BUDGET_CONSTANTS.UNIT_PRICE_MICRO_LAMPORTS
29
+ }), ComputeBudgetProgram.setComputeUnitLimit({
30
+ units: COMPUTE_BUDGET_CONSTANTS.UNIT_LIMIT
31
+ }), SystemProgram.transfer({
32
+ fromPubkey,
33
+ toPubkey,
34
+ lamports
35
+ })];
36
+ const transaction = new Transaction().add(...instructions);
37
+ transaction.feePayer = fromPubkey;
38
+ transaction.recentBlockhash = blockhash;
39
+ return transaction;
40
+ }
41
+ //# sourceMappingURL=createSendTransaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ComputeBudgetProgram","LAMPORTS_PER_SOL","PublicKey","SystemProgram","Transaction","COMPUTE_BUDGET_CONSTANTS","UNIT_PRICE_MICRO_LAMPORTS","UNIT_LIMIT","createSendTransaction","fromAddress","toAddress","value","connection","fromPubkey","toPubkey","lamports","Math","floor","blockhash","getLatestBlockhash","instructions","setComputeUnitPrice","microLamports","setComputeUnitLimit","units","transfer","transaction","add","feePayer","recentBlockhash"],"sourceRoot":"../../../src","sources":["utils/createSendTransaction.ts"],"mappings":";;AAAA,SACEA,oBAAoB,EAEpBC,gBAAgB,EAChBC,SAAS,EACTC,aAAa,EACbC,WAAW,QACN,iBAAiB;;AAExB;;AASA;AACA;AACA;AACA;AACA,MAAMC,wBAAwB,GAAG;EAC/BC,yBAAyB,EAAE,QAAQ;EACnCC,UAAU,EAAE;AACd,CAAC;AAED,OAAO,eAAeC,qBAAqBA,CAAC;EAC1CC,WAAW;EACXC,SAAS;EACTC,KAAK;EACLC;AACmB,CAAC,EAAwB;EAC5C,MAAMC,UAAU,GAAG,IAAIX,SAAS,CAACO,WAAW,CAAC;EAC7C,MAAMK,QAAQ,GAAG,IAAIZ,SAAS,CAACQ,SAAS,CAAC;EACzC,MAAMK,QAAQ,GAAGC,IAAI,CAACC,KAAK,CAACN,KAAK,GAAGV,gBAAgB,CAAC;EAErD,MAAM;IAAEiB;EAAU,CAAC,GAAG,MAAMN,UAAU,CAACO,kBAAkB,CAAC,CAAC;EAE3D,MAAMC,YAAY,GAAG,CACnBpB,oBAAoB,CAACqB,mBAAmB,CAAC;IACvCC,aAAa,EAAEjB,wBAAwB,CAACC;EAC1C,CAAC,CAAC,EACFN,oBAAoB,CAACuB,mBAAmB,CAAC;IAAEC,KAAK,EAAEnB,wBAAwB,CAACE;EAAW,CAAC,CAAC,EACxFJ,aAAa,CAACsB,QAAQ,CAAC;IACrBZ,UAAU;IACVC,QAAQ;IACRC;EACF,CAAC,CAAC,CACH;EAED,MAAMW,WAAW,GAAG,IAAItB,WAAW,CAAC,CAAC,CAACuB,GAAG,CAAC,GAAGP,YAAY,CAAC;EAC1DM,WAAW,CAACE,QAAQ,GAAGf,UAAU;EACjCa,WAAW,CAACG,eAAe,GAAGX,SAAS;EAEvC,OAAOQ,WAAW;AACpB","ignoreList":[]}
@@ -1,10 +1,18 @@
1
1
  import { SolanaBaseAdapter, type AppKitNetwork, type CaipAddress, type ChainNamespace, type GetBalanceParams, type GetBalanceResponse } from '@reown/appkit-common-react-native';
2
+ import { Transaction, VersionedTransaction } from '@solana/web3.js';
3
+ export interface SolanaTransactionData {
4
+ fromAddress: string;
5
+ toAddress: string;
6
+ amount: number;
7
+ network?: AppKitNetwork;
8
+ rpcUrl?: string;
9
+ }
2
10
  export declare class SolanaAdapter extends SolanaBaseAdapter {
3
11
  private static supportedNamespace;
4
- constructor(configParams: {
5
- projectId: string;
6
- });
12
+ constructor();
7
13
  getBalance(params: GetBalanceParams): Promise<GetBalanceResponse>;
14
+ signTransaction<T extends Transaction | VersionedTransaction>(transaction: T, network?: AppKitNetwork): Promise<T>;
15
+ sendTransaction(data: SolanaTransactionData): Promise<string | null>;
8
16
  switchNetwork(network: AppKitNetwork): Promise<void>;
9
17
  getAccounts(): CaipAddress[] | undefined;
10
18
  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;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;IA8CjE,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
+ {"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;AAIhF,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;CACjB;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;IAiEP,eAAe,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAsEpE,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,4 +1,4 @@
1
- import { WalletConnector, type AppKitNetwork, type CaipNetworkId, type ChainNamespace, type ConnectOptions, type Namespaces, type WalletInfo, type ConnectorInitOptions } from '@reown/appkit-common-react-native';
1
+ import { WalletConnector, type AppKitNetwork, type CaipNetworkId, type ChainNamespace, type ConnectOptions, type Namespaces, type WalletInfo, type ConnectorInitOptions, type ConnectionProperties } from '@reown/appkit-common-react-native';
2
2
  import { PhantomProvider } from '../providers/PhantomProvider';
3
3
  import type { PhantomConnectorConfig } from '../types';
4
4
  export declare class PhantomConnector extends WalletConnector {
@@ -16,6 +16,7 @@ export declare class PhantomConnector extends WalletConnector {
16
16
  private getStorage;
17
17
  getNamespaces(): Namespaces;
18
18
  getChainId(namespace: ChainNamespace): CaipNetworkId | undefined;
19
+ getProperties(): ConnectionProperties | undefined;
19
20
  getWalletInfo(): WalletInfo | undefined;
20
21
  isConnected(): boolean;
21
22
  switchNetwork(network: AppKitNetwork): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"PhantomConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/PhantomConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EAEf,KAAK,oBAAoB,EAK1B,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAC;AACvF,OAAO,KAAK,EAEV,sBAAsB,EAGvB,MAAM,UAAU,CAAC;AAWlB,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAEhD,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,qBAAqB,CAAC,CAAkB;IAEhD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAA4B;gBAE3D,MAAM,CAAC,EAAE,sBAAsB;IAK5B,IAAI,CAAC,GAAG,EAAE,oBAAoB;YAuB/B,iBAAiB;IAqBhB,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IA0D/D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAY5B,YAAY;IAOjB,WAAW,IAAI,eAAe;IAQvC,OAAO,CAAC,UAAU;IAQT,aAAa,IAAI,UAAU;IAQ3B,UAAU,CAAC,SAAS,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS;IAQhE,aAAa,IAAI,UAAU,GAAG,SAAS;IAQhD,WAAW,IAAI,OAAO;IAKP,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDtD,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;YAuCjC,WAAW;YAmBX,mBAAmB;CAOlC"}
1
+ {"version":3,"file":"PhantomConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/PhantomConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EAEf,KAAK,oBAAoB,EAKzB,KAAK,oBAAoB,EAE1B,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAC;AACvF,OAAO,KAAK,EAEV,sBAAsB,EAGvB,MAAM,UAAU,CAAC;AAWlB,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,qBAAqB,CAAC,CAAkB;IAEhD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAA4B;gBAE3D,MAAM,CAAC,EAAE,sBAAsB;IAK5B,IAAI,CAAC,GAAG,EAAE,oBAAoB;YAuB/B,iBAAiB;IAqBhB,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAuD/D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAiB5B,YAAY;IAOjB,WAAW,IAAI,eAAe;IAQvC,OAAO,CAAC,UAAU;IAQT,aAAa,IAAI,UAAU;IAQ3B,UAAU,CAAC,SAAS,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS;IAQhE,aAAa,IAAI,oBAAoB,GAAG,SAAS;IAIjD,aAAa,IAAI,UAAU,GAAG,SAAS;IAQhD,WAAW,IAAI,OAAO;IAKP,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CpD,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;YAuCnC,WAAW;YAmBX,mBAAmB;CAOlC"}
@@ -1,4 +1,4 @@
1
- export { PhantomConnector } from './connectors/PhantomConnector';
2
- export type { PhantomConnectorConfig } from './types';
3
1
  export { SolanaAdapter } from './adapter';
2
+ export type { PhantomConnectorConfig } from './types';
3
+ export { PhantomConnector } from './connectors/PhantomConnector';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,YAAY,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,YAAY,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -16,7 +16,21 @@ export declare class PhantomProvider extends EventEmitter implements Provider {
16
16
  private sessionToken;
17
17
  private userPublicKey;
18
18
  private phantomEncryptionPublicKeyBs58;
19
+ private activeSubscription;
20
+ private isOperationPending;
19
21
  constructor(config: PhantomProviderConfig);
22
+ /**
23
+ * Cleanup method to be called when the provider is destroyed
24
+ */
25
+ destroy(): void;
26
+ /**
27
+ * Safely cleanup the active subscription
28
+ */
29
+ private cleanupActiveSubscription;
30
+ /**
31
+ * Safely set a new subscription, ensuring no operation is pending
32
+ */
33
+ private setActiveSubscription;
20
34
  getUserPublicKey(): string | null;
21
35
  isConnected(): boolean;
22
36
  private buildUrl;
@@ -1 +1 @@
1
- {"version":3,"file":"PhantomProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/PhantomProvider.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,aAAa,EAEd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EAYd,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,YAAY,MAAM,QAAQ,CAAC;AAKlC,eAAO,MAAM,sBAAsB;;;;;CAKzB,CAAC;AAQX,qBAAa,eAAgB,SAAQ,YAAa,YAAW,QAAQ;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,cAAc,CAAkC;IAExD,OAAO,CAAC,OAAO,CAAU;IAEzB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,8BAA8B,CAAuB;gBAEjD,MAAM,EAAE,qBAAqB;IAOzC,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,cAAc;IAyBT,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;YAkBjC,WAAW;YAiBX,mBAAmB;IAQpB,OAAO,CAAC,CAAC,GAAG,oBAAoB,EAAE,MAAM,CAAC,EAAE;QACtD,OAAO,CAAC,EAAE,cAAc,CAAC;KAC1B,GAAG,OAAO,CAAC,CAAC,CAAC;IAgFD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD3B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAOnC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC;CA8LtF"}
1
+ {"version":3,"file":"PhantomProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/PhantomProvider.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,aAAa,EAEd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EAYd,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,YAAY,MAAM,QAAQ,CAAC;AAKlC,eAAO,MAAM,sBAAsB;;;;;CAKzB,CAAC;AAQX,qBAAa,eAAgB,SAAQ,YAAa,YAAW,QAAQ;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,cAAc,CAAkC;IAExD,OAAO,CAAC,OAAO,CAAU;IAEzB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,8BAA8B,CAAuB;IAG7D,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,MAAM,EAAE,qBAAqB;IAOzC;;OAEG;IACI,OAAO,IAAI,IAAI;IAKtB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAQjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAS7B,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,cAAc;IAyBT,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;YAkBjC,WAAW;YAiBX,mBAAmB;IAQpB,OAAO,CAAC,CAAC,GAAG,oBAAoB,EAAE,MAAM,CAAC,EAAE;QACtD,OAAO,CAAC,EAAE,cAAc,CAAC;KAC1B,GAAG,OAAO,CAAC,CAAC,CAAC;IAuFD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2D3B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQnC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAOnC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC;CAiMtF"}
@@ -0,0 +1,10 @@
1
+ import { type Connection, Transaction } from '@solana/web3.js';
2
+ type SendTransactionArgs = {
3
+ connection: Connection;
4
+ fromAddress: string;
5
+ toAddress: string;
6
+ value: number;
7
+ };
8
+ export declare function createSendTransaction({ fromAddress, toAddress, value, connection }: SendTransactionArgs): Promise<Transaction>;
9
+ export {};
10
+ //# sourceMappingURL=createSendTransaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSendTransaction.d.ts","sourceRoot":"","sources":["../../../src/utils/createSendTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAIf,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAIzB,KAAK,mBAAmB,GAAG;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAWF,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,SAAS,EACT,KAAK,EACL,UAAU,EACX,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwB5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reown/appkit-solana-react-native",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-alpha.3",
4
4
  "main": "lib/commonjs/index.js",
5
5
  "types": "lib/typescript/index.d.ts",
6
6
  "module": "lib/module/index.js",
@@ -28,7 +28,7 @@
28
28
  "react-native"
29
29
  ],
30
30
  "repository": "https://github.com/reown-com/appkit-react-native",
31
- "author": "Reown <support@reown.com> (https://reown.com)",
31
+ "author": "Reown (https://discord.gg/reown)",
32
32
  "homepage": "https://reown.com/appkit",
33
33
  "license": "Apache-2.0",
34
34
  "bugs": {
@@ -39,8 +39,14 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@reown/appkit-common-react-native": "2.0.0-alpha.1",
42
+ "@reown/appkit-common-react-native": "2.0.0-alpha.3",
43
+ "@solana/web3.js": "1.98.2",
43
44
  "bs58": "6.0.0",
44
45
  "tweetnacl": "1.0.3"
46
+ },
47
+ "peerDependencies": {
48
+ "@walletconnect/react-native-compat": ">=2.16.1",
49
+ "react": ">=18",
50
+ "react-native": ">=0.72"
45
51
  }
46
52
  }
package/src/adapter.ts CHANGED
@@ -7,14 +7,25 @@ import {
7
7
  type GetBalanceResponse
8
8
  } from '@reown/appkit-common-react-native';
9
9
  import { getSolanaNativeBalance, getSolanaTokenBalance } from './helpers';
10
+ import { Connection, Transaction, VersionedTransaction } from '@solana/web3.js';
11
+ import base58 from 'bs58';
12
+ import { createSendTransaction } from './utils/createSendTransaction';
13
+
14
+ export interface SolanaTransactionData {
15
+ fromAddress: string;
16
+ toAddress: string;
17
+ amount: number;
18
+ network?: AppKitNetwork;
19
+ rpcUrl?: string;
20
+ }
10
21
 
11
22
  export class SolanaAdapter extends SolanaBaseAdapter {
12
23
  private static supportedNamespace: ChainNamespace = 'solana';
13
24
 
14
- constructor(configParams: { projectId: string }) {
25
+ constructor() {
15
26
  super({
16
- projectId: configParams.projectId,
17
- supportedNamespace: SolanaAdapter.supportedNamespace
27
+ supportedNamespace: SolanaAdapter.supportedNamespace,
28
+ adapterType: 'solana'
18
29
  });
19
30
  }
20
31
 
@@ -64,6 +75,144 @@ export class SolanaAdapter extends SolanaBaseAdapter {
64
75
  }
65
76
  }
66
77
 
78
+ async signTransaction<T extends Transaction | VersionedTransaction>(
79
+ transaction: T,
80
+ network?: AppKitNetwork
81
+ ): Promise<T> {
82
+ if (!this.connector) {
83
+ throw new Error('SolanaAdapter:signTransaction - no active connector');
84
+ }
85
+
86
+ if (!network) {
87
+ throw new Error('SolanaAdapter:signTransaction - network is undefined');
88
+ }
89
+
90
+ const provider = this.connector.getProvider();
91
+ if (!provider) {
92
+ throw new Error('SolanaAdapter:signTransaction - provider is undefined');
93
+ }
94
+
95
+ try {
96
+ // Serialize transaction to base64 (following WalletConnect standard)
97
+ const serializedTransaction = Buffer.from(
98
+ new Uint8Array(transaction.serialize({ verifySignatures: false }))
99
+ ).toString('base64');
100
+
101
+ const result = (await provider.request(
102
+ {
103
+ method: 'solana_signTransaction',
104
+ params: {
105
+ transaction: serializedTransaction,
106
+ pubkey: this.getAccounts()?.[0]?.split(':')[2] || ''
107
+ }
108
+ },
109
+ network.caipNetworkId
110
+ )) as { signature?: string; transaction?: string };
111
+
112
+ // Handle different response formats
113
+ if ('signature' in result && result.signature) {
114
+ // Old RPC response format - add signature to transaction
115
+ const decoded = base58.decode(result.signature);
116
+ if (transaction instanceof Transaction && transaction.feePayer) {
117
+ transaction.addSignature(
118
+ transaction.feePayer,
119
+ Buffer.from(decoded) as Buffer & Uint8Array
120
+ );
121
+ }
122
+
123
+ return transaction;
124
+ }
125
+
126
+ if ('transaction' in result && result.transaction) {
127
+ // New response format - deserialize the signed transaction
128
+ const decodedTransaction = Buffer.from(result.transaction, 'base64');
129
+
130
+ if (transaction instanceof VersionedTransaction) {
131
+ return VersionedTransaction.deserialize(new Uint8Array(decodedTransaction)) as T;
132
+ }
133
+
134
+ return Transaction.from(decodedTransaction) as T;
135
+ }
136
+
137
+ throw new Error('SolanaAdapter:signTransaction - invalid response format');
138
+ } catch (error) {
139
+ if (error instanceof Error) {
140
+ throw new Error(`SolanaAdapter:signTransaction - ${error.message}`);
141
+ }
142
+ throw new Error('SolanaAdapter:signTransaction - unknown error occurred');
143
+ }
144
+ }
145
+
146
+ async sendTransaction(data: SolanaTransactionData): Promise<string | null> {
147
+ const { fromAddress, toAddress, amount, network, rpcUrl } = data;
148
+
149
+ if (!this.connector) {
150
+ throw new Error('SolanaAdapter:sendTransaction - no active connector');
151
+ }
152
+
153
+ const provider = this.connector.getProvider();
154
+ if (!provider) {
155
+ throw new Error('SolanaAdapter:sendTransaction - provider is undefined');
156
+ }
157
+
158
+ if (!network) {
159
+ throw new Error('SolanaAdapter:sendTransaction - network is undefined');
160
+ }
161
+
162
+ if (!fromAddress) {
163
+ throw new Error('SolanaAdapter:sendTransaction - fromAddress is undefined');
164
+ }
165
+
166
+ if (!toAddress) {
167
+ throw new Error('SolanaAdapter:sendTransaction - toAddress is undefined');
168
+ }
169
+
170
+ if (!amount || amount <= 0) {
171
+ throw new Error('SolanaAdapter:sendTransaction - amount must be greater than 0');
172
+ }
173
+
174
+ try {
175
+ // Determine RPC URL
176
+ let connectionRpcUrl = rpcUrl;
177
+ if (!connectionRpcUrl && network) {
178
+ connectionRpcUrl = network.rpcUrls?.default?.http?.[0];
179
+ }
180
+ if (!connectionRpcUrl) {
181
+ throw new Error('SolanaAdapter:sendTransaction - no RPC URL available');
182
+ }
183
+
184
+ // Create connection
185
+ const connection = new Connection(connectionRpcUrl, 'confirmed');
186
+
187
+ const transaction = await createSendTransaction({
188
+ connection,
189
+ fromAddress,
190
+ toAddress,
191
+ value: amount
192
+ });
193
+
194
+ // Sign the transaction
195
+ const signedTransaction = await this.signTransaction(transaction, network);
196
+
197
+ // Send the signed transaction
198
+ const signature = await connection.sendRawTransaction(signedTransaction.serialize(), {
199
+ skipPreflight: false,
200
+ preflightCommitment: 'confirmed'
201
+ });
202
+
203
+ if (!signature) {
204
+ throw new Error('SolanaAdapter:sendTransaction - no signature returned');
205
+ }
206
+
207
+ return signature;
208
+ } catch (error) {
209
+ if (error instanceof Error) {
210
+ throw new Error(`SolanaAdapter:sendTransaction - ${error.message}`);
211
+ }
212
+ throw new Error('SolanaAdapter:sendTransaction - unknown error occurred');
213
+ }
214
+ }
215
+
67
216
  async switchNetwork(network: AppKitNetwork): Promise<void> {
68
217
  if (!this.connector) throw new Error('No active connector');
69
218
 
@@ -11,7 +11,9 @@ import {
11
11
  type Storage,
12
12
  solana,
13
13
  solanaDevnet,
14
- solanaTestnet
14
+ solanaTestnet,
15
+ type ConnectionProperties,
16
+ ConstantsUtil
15
17
  } from '@reown/appkit-common-react-native';
16
18
  import nacl from 'tweetnacl';
17
19
  import bs58 from 'bs58';
@@ -24,10 +26,10 @@ import type {
24
26
  PhantomProviderConfig
25
27
  } from '../types';
26
28
 
27
- const SOLANA_CLUSTER_TO_CHAIN_ID_PART: Record<PhantomCluster, string> = {
28
- 'mainnet-beta': solana.id as string,
29
- 'testnet': solanaTestnet.id as string,
30
- 'devnet': solanaDevnet.id as string
29
+ const SOLANA_CLUSTER_TO_CHAIN_ID: Record<PhantomCluster, CaipNetworkId> = {
30
+ 'mainnet-beta': solana.caipNetworkId,
31
+ 'testnet': solanaTestnet.caipNetworkId,
32
+ 'devnet': solanaDevnet.caipNetworkId
31
33
  };
32
34
 
33
35
  const PHANTOM_CONNECTOR_STORAGE_KEY = '@appkit/phantom-connector-data';
@@ -35,7 +37,6 @@ const DAPP_KEYPAIR_STORAGE_KEY = '@appkit/phantom-dapp-secret-key';
35
37
 
36
38
  export class PhantomConnector extends WalletConnector {
37
39
  private readonly config: PhantomConnectorConfig;
38
-
39
40
  private currentCaipNetworkId: CaipNetworkId | null = null;
40
41
  private dappEncryptionKeyPair?: nacl.BoxKeyPair;
41
42
 
@@ -51,10 +52,10 @@ export class PhantomConnector extends WalletConnector {
51
52
  this.storage = ops.storage;
52
53
  await this.initializeKeyPair();
53
54
 
54
- const appScheme = ops.metadata.redirect?.universal;
55
+ const appScheme = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
55
56
  if (!appScheme) {
56
57
  throw new Error(
57
- 'Phantom Connector: No universal link found in metadata. Please add redirect.universal to the metadata.'
58
+ 'Phantom Connector: No redirect link found in metadata. Please add redirect.universal or redirect.native to the metadata.'
58
59
  );
59
60
  }
60
61
 
@@ -95,33 +96,30 @@ export class PhantomConnector extends WalletConnector {
95
96
  return this.namespaces;
96
97
  }
97
98
 
98
- const defaultChain =
99
+ const defaultChain: CaipNetworkId | undefined =
99
100
  opts?.defaultChain?.split(':')?.[0] === 'solana'
100
- ? opts?.defaultChain?.split(':')[1]
101
- : opts?.namespaces?.['solana']?.chains?.[0]?.split(':')[1];
101
+ ? opts?.defaultChain
102
+ : opts?.namespaces?.['solana']?.chains?.[0];
102
103
 
103
104
  const requestedCluster =
104
105
  this.config.cluster ??
105
- (Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(
106
- key =>
107
- SOLANA_CLUSTER_TO_CHAIN_ID_PART[key as keyof typeof SOLANA_CLUSTER_TO_CHAIN_ID_PART] ===
108
- defaultChain
106
+ (Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID).find(
107
+ key => SOLANA_CLUSTER_TO_CHAIN_ID[key as PhantomCluster] === defaultChain
109
108
  ) as PhantomCluster | undefined);
110
109
 
111
110
  try {
112
111
  const connectResult = await this.getProvider().connect({ cluster: requestedCluster });
113
112
 
114
- const solanaChainIdPart = SOLANA_CLUSTER_TO_CHAIN_ID_PART[connectResult.cluster];
115
- if (!solanaChainIdPart) {
113
+ const solanaChainId = SOLANA_CLUSTER_TO_CHAIN_ID[connectResult.cluster];
114
+ if (!solanaChainId) {
116
115
  throw new Error(
117
116
  `Phantom Connect: Internal - Unknown cluster mapping for ${connectResult.cluster}`
118
117
  );
119
118
  }
120
- this.currentCaipNetworkId = `solana:${solanaChainIdPart}` as CaipNetworkId;
119
+ this.currentCaipNetworkId = solanaChainId;
121
120
 
122
121
  this.wallet = {
123
- name: 'Phantom Wallet',
124
- id: 'phantom-wallet'
122
+ name: ConstantsUtil.PHANTOM_CUSTOM_WALLET.name
125
123
  };
126
124
 
127
125
  const userPublicKey = this.getProvider().getUserPublicKey();
@@ -149,14 +147,19 @@ export class PhantomConnector extends WalletConnector {
149
147
  }
150
148
 
151
149
  override async disconnect(): Promise<void> {
152
- if (!this.isConnected()) {
153
- return Promise.resolve();
154
- }
155
150
  try {
156
- await this.getProvider().disconnect();
151
+ if (this.isConnected()) {
152
+ await super.disconnect();
153
+ }
157
154
  } catch (error: any) {
158
155
  // console.warn(`PhantomConnector: Error during provider disconnect: ${error.message}. Proceeding with local clear.`);
159
156
  }
157
+
158
+ // Cleanup provider resources
159
+ if (this.provider) {
160
+ (this.provider as PhantomProvider).destroy();
161
+ }
162
+
160
163
  await this.clearSession();
161
164
  }
162
165
 
@@ -199,6 +202,10 @@ export class PhantomConnector extends WalletConnector {
199
202
  return undefined;
200
203
  }
201
204
 
205
+ override getProperties(): ConnectionProperties | undefined {
206
+ return this.properties;
207
+ }
208
+
202
209
  override getWalletInfo(): WalletInfo | undefined {
203
210
  if (!this.isConnected()) {
204
211
  return undefined;
@@ -213,40 +220,34 @@ export class PhantomConnector extends WalletConnector {
213
220
  }
214
221
 
215
222
  override async switchNetwork(network: AppKitNetwork): Promise<void> {
216
- const targetClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(
217
- key =>
218
- SOLANA_CLUSTER_TO_CHAIN_ID_PART[key as keyof typeof SOLANA_CLUSTER_TO_CHAIN_ID_PART] ===
219
- network.id
223
+ const targetClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID).find(
224
+ key => SOLANA_CLUSTER_TO_CHAIN_ID[key as PhantomCluster] === network.caipNetworkId
220
225
  ) as PhantomCluster | undefined;
221
226
 
222
227
  if (!targetClusterName) {
223
228
  throw new Error(`Cannot switch to unsupported network ID: ${network.id}`);
224
229
  }
225
230
 
226
- const currentClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(
227
- key =>
228
- `solana:${
229
- SOLANA_CLUSTER_TO_CHAIN_ID_PART[key as keyof typeof SOLANA_CLUSTER_TO_CHAIN_ID_PART]
230
- }` === this.currentCaipNetworkId
231
+ const currentClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID).find(
232
+ key => SOLANA_CLUSTER_TO_CHAIN_ID[key as PhantomCluster] === this.currentCaipNetworkId
231
233
  ) as PhantomCluster | undefined;
232
234
 
233
235
  if (targetClusterName === currentClusterName && this.isConnected()) {
234
236
  return Promise.resolve();
235
237
  }
236
238
 
237
- // For deeplink wallets, switching network effectively means re-connecting to the new cluster.
238
- // We can try to disconnect the current session and then initiate a new connection.
239
- // console.log(`Attempting to switch network to: ${targetClusterName}`);
239
+ // Phantom doesn't provide a way to switch network, so we need to disconnect and reconnect.
240
240
  await this.disconnect(); // Clear current session
241
241
 
242
242
  // Create a temporary options object to guide the new connection
243
243
  const tempConnectOpts: ConnectOptions = {
244
- defaultChain: `solana:${SOLANA_CLUSTER_TO_CHAIN_ID_PART[targetClusterName]}` as CaipNetworkId
244
+ defaultChain: SOLANA_CLUSTER_TO_CHAIN_ID[targetClusterName]
245
245
  };
246
246
 
247
247
  // Attempt to connect to the new cluster
248
248
  // The connect method will use the defaultChain from opts to determine the cluster.
249
249
  await this.connect(tempConnectOpts);
250
+ this.getProvider().emit('chainChanged', network.id);
250
251
 
251
252
  // Verify if the connection was successful and to the correct new network
252
253
  if (
@@ -260,7 +261,7 @@ export class PhantomConnector extends WalletConnector {
260
261
  }
261
262
 
262
263
  // Orchestrates session restoration
263
- public async restoreSession(): Promise<boolean> {
264
+ override async restoreSession(): Promise<boolean> {
264
265
  try {
265
266
  const providerSession = await this.getProvider().restoreSession();
266
267
  if (!providerSession) {
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
- // Connectors
2
- export { PhantomConnector } from './connectors/PhantomConnector';
1
+ // Adapter
2
+ export { SolanaAdapter } from './adapter';
3
3
 
4
4
  // Types
5
5
  export type { PhantomConnectorConfig } from './types';
6
6
 
7
- // Adapter
8
- export { SolanaAdapter } from './adapter';
7
+ // Connectors
8
+ export { PhantomConnector } from './connectors/PhantomConnector';