@reown/appkit-coinbase-react-native 0.0.0-chore-bump-builder-20250728194329

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 (37) hide show
  1. package/lib/commonjs/connectors/CoinbaseConnector.js +134 -0
  2. package/lib/commonjs/connectors/CoinbaseConnector.js.map +1 -0
  3. package/lib/commonjs/index.js +13 -0
  4. package/lib/commonjs/index.js.map +1 -0
  5. package/lib/commonjs/package.json +1 -0
  6. package/lib/commonjs/providers/CoinbaseProvider.js +97 -0
  7. package/lib/commonjs/providers/CoinbaseProvider.js.map +1 -0
  8. package/lib/commonjs/types.js +6 -0
  9. package/lib/commonjs/types.js.map +1 -0
  10. package/lib/commonjs/utils.js +45 -0
  11. package/lib/commonjs/utils.js.map +1 -0
  12. package/lib/module/connectors/CoinbaseConnector.js +129 -0
  13. package/lib/module/connectors/CoinbaseConnector.js.map +1 -0
  14. package/lib/module/index.js +4 -0
  15. package/lib/module/index.js.map +1 -0
  16. package/lib/module/providers/CoinbaseProvider.js +91 -0
  17. package/lib/module/providers/CoinbaseProvider.js.map +1 -0
  18. package/lib/module/types.js +4 -0
  19. package/lib/module/types.js.map +1 -0
  20. package/lib/module/utils.js +39 -0
  21. package/lib/module/utils.js.map +1 -0
  22. package/lib/typescript/connectors/CoinbaseConnector.d.ts +22 -0
  23. package/lib/typescript/connectors/CoinbaseConnector.d.ts.map +1 -0
  24. package/lib/typescript/index.d.ts +3 -0
  25. package/lib/typescript/index.d.ts.map +1 -0
  26. package/lib/typescript/providers/CoinbaseProvider.d.ts +18 -0
  27. package/lib/typescript/providers/CoinbaseProvider.d.ts.map +1 -0
  28. package/lib/typescript/types.d.ts +17 -0
  29. package/lib/typescript/types.d.ts.map +1 -0
  30. package/lib/typescript/utils.d.ts +16 -0
  31. package/lib/typescript/utils.d.ts.map +1 -0
  32. package/package.json +64 -0
  33. package/src/connectors/CoinbaseConnector.ts +163 -0
  34. package/src/index.ts +2 -0
  35. package/src/providers/CoinbaseProvider.ts +112 -0
  36. package/src/types.ts +27 -0
  37. package/src/utils.ts +53 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CoinbaseConnector = void 0;
7
+ var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
8
+ var _utils = require("../utils");
9
+ var _CoinbaseProvider = require("../providers/CoinbaseProvider");
10
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
11
+ class CoinbaseConnector extends _appkitCommonReactNative.WalletConnector {
12
+ static SUPPORTED_NAMESPACE = 'eip155';
13
+ constructor(config) {
14
+ super({
15
+ type: 'coinbase'
16
+ });
17
+ this.config = config ?? {};
18
+ }
19
+ async init(ops) {
20
+ super.init(ops);
21
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
22
+ if (!redirect) {
23
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
24
+ }
25
+ this.provider = new _CoinbaseProvider.CoinbaseProvider({
26
+ redirect,
27
+ // use config storage, as it needs to be mmkv-compatible
28
+ storage: this.config.storage
29
+ });
30
+ await this.restoreSession();
31
+ }
32
+ async connect(opts) {
33
+ const accounts = await this.getProvider().connect();
34
+ const namespaces = (0, _utils.getCoinbaseNamespace)(opts?.namespaces, accounts);
35
+ this.namespaces = namespaces;
36
+ this.saveSession(namespaces);
37
+ return this.namespaces;
38
+ }
39
+ async disconnect() {
40
+ await super.disconnect();
41
+ this.deleteSession();
42
+ }
43
+ getProvider() {
44
+ if (!this.provider) {
45
+ throw new Error('CoinbaseConnector: Provider not initialized');
46
+ }
47
+ return this.provider;
48
+ }
49
+ getNamespaces() {
50
+ if (!this.namespaces) {
51
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
52
+ }
53
+ return this.namespaces;
54
+ }
55
+ getChainId() {
56
+ const hexChainId = this.getProvider().getChainId();
57
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
58
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
59
+ }
60
+ getWalletInfo() {
61
+ // TODO: Add icon
62
+ return {
63
+ name: 'Coinbase Wallet',
64
+ description: 'Your home to everything onchain',
65
+ url: 'https://www.coinbase.com/wallet'
66
+ };
67
+ }
68
+ getProperties() {
69
+ return undefined;
70
+ }
71
+ async switchNetwork(network) {
72
+ const provider = this.getProvider();
73
+ const chainId_ = _appkitCommonReactNative.NumberUtil.convertNumericToHexString(network.id);
74
+ try {
75
+ await provider.request({
76
+ method: 'wallet_switchEthereumChain',
77
+ params: [{
78
+ chainId: chainId_
79
+ }]
80
+ });
81
+ } catch (error) {
82
+ // Indicates chain is not added to provider
83
+ if (error?.code === 4902) {
84
+ try {
85
+ await provider.request({
86
+ method: 'wallet_addEthereumChain',
87
+ params: [{
88
+ chainId: chainId_,
89
+ chainName: network.name,
90
+ nativeCurrency: network.nativeCurrency,
91
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
92
+ blockExplorerUrls: [network.blockExplorers?.default.url]
93
+ }]
94
+ });
95
+ } catch (e) {
96
+ console.warn('CoinbaseConnector: switchNetwork error', e);
97
+ throw e;
98
+ }
99
+ }
100
+ console.warn('CoinbaseConnector: switchNetwork error', error);
101
+ throw error;
102
+ }
103
+ }
104
+ deleteSession() {
105
+ const storage = this.getStorage();
106
+ storage.removeItem(SESSION_KEY);
107
+ }
108
+ saveSession(namespaces) {
109
+ const storage = this.getStorage();
110
+ storage.setItem(SESSION_KEY, {
111
+ namespaces
112
+ });
113
+ }
114
+ async restoreSession() {
115
+ const storage = this.getStorage();
116
+ const session = await storage.getItem(SESSION_KEY);
117
+ if (!session) {
118
+ return false;
119
+ }
120
+ const {
121
+ namespaces
122
+ } = session;
123
+ this.namespaces = namespaces;
124
+ return true;
125
+ }
126
+ getStorage() {
127
+ if (!this.storage) {
128
+ throw new Error('CoinbaseConnector: Storage not initialized');
129
+ }
130
+ return this.storage;
131
+ }
132
+ }
133
+ exports.CoinbaseConnector = CoinbaseConnector;
134
+ //# sourceMappingURL=CoinbaseConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_appkitCommonReactNative","require","_utils","_CoinbaseProvider","SESSION_KEY","CoinbaseConnector","WalletConnector","SUPPORTED_NAMESPACE","constructor","config","type","init","ops","redirect","metadata","universal","native","Error","provider","CoinbaseProvider","storage","restoreSession","connect","opts","accounts","getProvider","namespaces","getCoinbaseNamespace","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","StringUtil","hexToString","getWalletInfo","name","description","url","getProperties","undefined","switchNetwork","network","chainId_","NumberUtil","convertNumericToHexString","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","e","console","warn","getStorage","removeItem","setItem","session","getItem","exports"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "CoinbaseConnector", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _CoinbaseConnector.CoinbaseConnector;
10
+ }
11
+ });
12
+ var _CoinbaseConnector = require("./connectors/CoinbaseConnector");
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_CoinbaseConnector","require"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;AAAA,IAAAA,kBAAA,GAAAC,OAAA","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CoinbaseProvider = void 0;
7
+ var _events = _interopRequireDefault(require("events"));
8
+ var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
9
+ var _walletMobileSdk = require("@coinbase/wallet-mobile-sdk");
10
+ var _utils = require("../utils");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ class CoinbaseProvider extends _events.default {
13
+ chainChangedListeners = new Map();
14
+ constructor(config) {
15
+ super();
16
+ this.config = config;
17
+ (0, _walletMobileSdk.configure)({
18
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
19
+ callbackURL: new URL(this.config.redirect),
20
+ // App Universal Link
21
+ hostPackageName: 'org.toshi'
22
+ });
23
+ this.provider = new _walletMobileSdk.WalletMobileSDKEVMProvider({
24
+ ...this.config,
25
+ jsonRpcUrl: this.config.rpcUrl,
26
+ chainId: this.config.defaultChain,
27
+ storage: this.config.storage
28
+ });
29
+ }
30
+ async connect() {
31
+ try {
32
+ let accounts = [];
33
+ const isConnected = this.provider.connected;
34
+ if (!isConnected) {
35
+ accounts = await this.provider.request({
36
+ method: 'eth_requestAccounts',
37
+ params: []
38
+ });
39
+ } else {
40
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
41
+ }
42
+ return accounts;
43
+ } catch (error) {
44
+ console.warn('CoinbaseProvider: connect error', error);
45
+ throw error;
46
+ }
47
+ }
48
+ async disconnect() {
49
+ this.provider.disconnect();
50
+ return Promise.resolve();
51
+ }
52
+ request(args) {
53
+ if (!(0, _utils.isValidMethod)(args.method)) {
54
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
55
+ }
56
+ return this.provider.request(args);
57
+ }
58
+ getChainId() {
59
+ return this.provider.chainId;
60
+ }
61
+ onChainChanged(hexChainId) {
62
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
63
+ this.emit('chainChanged', {
64
+ chainId
65
+ });
66
+ }
67
+ on(event, listener) {
68
+ if (event === 'chainChanged') {
69
+ // Create middleware that formats the chain ID before calling the original listener
70
+ const chainChangedMiddleware = hexChainId => {
71
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
72
+ listener(chainId);
73
+ };
74
+
75
+ // Store the mapping between original listener and middleware
76
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
77
+ return this.provider.on('chainChanged', chainChangedMiddleware);
78
+ }
79
+ return this.provider.on(event, listener);
80
+ }
81
+ off(event, listener) {
82
+ if (event === 'chainChanged') {
83
+ // Get the middleware wrapper for this listener
84
+ const middleware = this.chainChangedListeners.get(listener);
85
+ if (middleware) {
86
+ // Remove the middleware from the provider
87
+ this.provider.off('chainChanged', middleware);
88
+ // Remove the mapping
89
+ this.chainChangedListeners.delete(listener);
90
+ return this;
91
+ }
92
+ }
93
+ return this.provider.off(event, listener);
94
+ }
95
+ }
96
+ exports.CoinbaseProvider = CoinbaseProvider;
97
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_events","_interopRequireDefault","require","_appkitCommonReactNative","_walletMobileSdk","_utils","e","__esModule","default","CoinbaseProvider","EventEmitter","chainChangedListeners","Map","constructor","config","configure","hostURL","URL","callbackURL","redirect","hostPackageName","provider","WalletMobileSDKEVMProvider","jsonRpcUrl","rpcUrl","chainId","defaultChain","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","isValidMethod","Error","getChainId","onChainChanged","hexChainId","StringUtil","hexToString","emit","on","event","listener","chainChangedMiddleware","set","off","middleware","get","delete","exports"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.COINBASE_METHODS = void 0;
7
+ exports.getCoinbaseNamespace = getCoinbaseNamespace;
8
+ exports.isValidMethod = isValidMethod;
9
+ const COINBASE_METHODS = exports.COINBASE_METHODS = {
10
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
11
+ SIGN_TRANSACTION: 'eth_signTransaction',
12
+ SEND_TRANSACTION: 'eth_sendTransaction',
13
+ SIGN_MESSAGE: 'personal_sign',
14
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
15
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
16
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
17
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
18
+ WATCH_ASSET: 'wallet_watchAsset'
19
+ };
20
+ function isValidMethod(method) {
21
+ return Object.values(COINBASE_METHODS).includes(method);
22
+ }
23
+ function getCoinbaseNamespace(namespaces, accounts) {
24
+ if (!namespaces || !accounts) {
25
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
26
+ }
27
+ const namespace = namespaces['eip155'];
28
+ if (!namespace) {
29
+ throw new Error('CoinbaseConnector: Namespace not found');
30
+ }
31
+ let caipAddresses = [];
32
+ for (const account of accounts) {
33
+ namespace.chains?.forEach(chain => {
34
+ caipAddresses.push(`${chain}:${account}`);
35
+ });
36
+ }
37
+ return {
38
+ ['eip155']: {
39
+ ...namespace,
40
+ methods: Object.values(COINBASE_METHODS),
41
+ accounts: caipAddresses
42
+ }
43
+ };
44
+ }
45
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["COINBASE_METHODS","exports","REQUEST_ACCOUNTS","SIGN_TRANSACTION","SEND_TRANSACTION","SIGN_MESSAGE","SIGN_TYPED_DATA_V3","SIGN_TYPED_DATA_V4","SWITCH_CHAIN","ADD_ETHEREUM_CHAIN","WATCH_ASSET","isValidMethod","method","Object","values","includes","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;;;;;;;AAOO,MAAMA,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG;EAC9BE,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,YAAY,EAAE,eAAe;EAC7BC,kBAAkB,EAAE,sBAAsB;EAC1CC,kBAAkB,EAAE,sBAAsB;EAC1CC,YAAY,EAAE,4BAA4B;EAC1CC,kBAAkB,EAAE,yBAAyB;EAC7CC,WAAW,EAAE;AACf,CAAU;AAEH,SAASC,aAAaA,CAACC,MAAc,EAA4B;EACtE,OAAOC,MAAM,CAACC,MAAM,CAACd,gBAAgB,CAAC,CAACe,QAAQ,CAACH,MAAwB,CAAC;AAC3E;AAEO,SAASI,oBAAoBA,CAClCC,UAA+B,EAC/BC,QAAmB,EACP;EACZ,IAAI,CAACD,UAAU,IAAI,CAACC,QAAQ,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,qDAAqD,CAAC;EACxE;EAEA,MAAMC,SAAS,GAAGH,UAAU,CAAC,QAAQ,CAAC;EAEtC,IAAI,CAACG,SAAS,EAAE;IACd,MAAM,IAAID,KAAK,CAAC,wCAAwC,CAAC;EAC3D;EAEA,IAAIE,aAA4B,GAAG,EAAE;EAErC,KAAK,MAAMC,OAAO,IAAIJ,QAAQ,EAAE;IAC9BE,SAAS,CAACG,MAAM,EAAEC,OAAO,CAACC,KAAK,IAAI;MACjCJ,aAAa,CAACK,IAAI,CAAC,GAAGD,KAAK,IAAIH,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEd,MAAM,CAACC,MAAM,CAACd,gBAAgB,CAAC;MACxCkB,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+
3
+ import { WalletConnector, NumberUtil, StringUtil } from '@reown/appkit-common-react-native';
4
+ import { getCoinbaseNamespace } from '../utils';
5
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
6
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
7
+ export class CoinbaseConnector extends WalletConnector {
8
+ static SUPPORTED_NAMESPACE = 'eip155';
9
+ constructor(config) {
10
+ super({
11
+ type: 'coinbase'
12
+ });
13
+ this.config = config ?? {};
14
+ }
15
+ async init(ops) {
16
+ super.init(ops);
17
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
18
+ if (!redirect) {
19
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
20
+ }
21
+ this.provider = new CoinbaseProvider({
22
+ redirect,
23
+ // use config storage, as it needs to be mmkv-compatible
24
+ storage: this.config.storage
25
+ });
26
+ await this.restoreSession();
27
+ }
28
+ async connect(opts) {
29
+ const accounts = await this.getProvider().connect();
30
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
31
+ this.namespaces = namespaces;
32
+ this.saveSession(namespaces);
33
+ return this.namespaces;
34
+ }
35
+ async disconnect() {
36
+ await super.disconnect();
37
+ this.deleteSession();
38
+ }
39
+ getProvider() {
40
+ if (!this.provider) {
41
+ throw new Error('CoinbaseConnector: Provider not initialized');
42
+ }
43
+ return this.provider;
44
+ }
45
+ getNamespaces() {
46
+ if (!this.namespaces) {
47
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
48
+ }
49
+ return this.namespaces;
50
+ }
51
+ getChainId() {
52
+ const hexChainId = this.getProvider().getChainId();
53
+ const chainId = StringUtil.hexToString(hexChainId);
54
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
55
+ }
56
+ getWalletInfo() {
57
+ // TODO: Add icon
58
+ return {
59
+ name: 'Coinbase Wallet',
60
+ description: 'Your home to everything onchain',
61
+ url: 'https://www.coinbase.com/wallet'
62
+ };
63
+ }
64
+ getProperties() {
65
+ return undefined;
66
+ }
67
+ async switchNetwork(network) {
68
+ const provider = this.getProvider();
69
+ const chainId_ = NumberUtil.convertNumericToHexString(network.id);
70
+ try {
71
+ await provider.request({
72
+ method: 'wallet_switchEthereumChain',
73
+ params: [{
74
+ chainId: chainId_
75
+ }]
76
+ });
77
+ } catch (error) {
78
+ // Indicates chain is not added to provider
79
+ if (error?.code === 4902) {
80
+ try {
81
+ await provider.request({
82
+ method: 'wallet_addEthereumChain',
83
+ params: [{
84
+ chainId: chainId_,
85
+ chainName: network.name,
86
+ nativeCurrency: network.nativeCurrency,
87
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
88
+ blockExplorerUrls: [network.blockExplorers?.default.url]
89
+ }]
90
+ });
91
+ } catch (e) {
92
+ console.warn('CoinbaseConnector: switchNetwork error', e);
93
+ throw e;
94
+ }
95
+ }
96
+ console.warn('CoinbaseConnector: switchNetwork error', error);
97
+ throw error;
98
+ }
99
+ }
100
+ deleteSession() {
101
+ const storage = this.getStorage();
102
+ storage.removeItem(SESSION_KEY);
103
+ }
104
+ saveSession(namespaces) {
105
+ const storage = this.getStorage();
106
+ storage.setItem(SESSION_KEY, {
107
+ namespaces
108
+ });
109
+ }
110
+ async restoreSession() {
111
+ const storage = this.getStorage();
112
+ const session = await storage.getItem(SESSION_KEY);
113
+ if (!session) {
114
+ return false;
115
+ }
116
+ const {
117
+ namespaces
118
+ } = session;
119
+ this.namespaces = namespaces;
120
+ return true;
121
+ }
122
+ getStorage() {
123
+ if (!this.storage) {
124
+ throw new Error('CoinbaseConnector: Storage not initialized');
125
+ }
126
+ return this.storage;
127
+ }
128
+ }
129
+ //# sourceMappingURL=CoinbaseConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WalletConnector","NumberUtil","StringUtil","getCoinbaseNamespace","CoinbaseProvider","SESSION_KEY","CoinbaseConnector","SUPPORTED_NAMESPACE","constructor","config","type","init","ops","redirect","metadata","universal","native","Error","provider","storage","restoreSession","connect","opts","accounts","getProvider","namespaces","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","hexToString","getWalletInfo","name","description","url","getProperties","undefined","switchNetwork","network","chainId_","convertNumericToHexString","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","e","console","warn","getStorage","removeItem","setItem","session","getItem"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CoinbaseConnector"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,gCAAgC","ignoreList":[]}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ import EventEmitter from 'events';
4
+ import { StringUtil } from '@reown/appkit-common-react-native';
5
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
6
+ import { isValidMethod } from '../utils';
7
+ export class CoinbaseProvider extends EventEmitter {
8
+ chainChangedListeners = new Map();
9
+ constructor(config) {
10
+ super();
11
+ this.config = config;
12
+ configure({
13
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
14
+ callbackURL: new URL(this.config.redirect),
15
+ // App Universal Link
16
+ hostPackageName: 'org.toshi'
17
+ });
18
+ this.provider = new WalletMobileSDKEVMProvider({
19
+ ...this.config,
20
+ jsonRpcUrl: this.config.rpcUrl,
21
+ chainId: this.config.defaultChain,
22
+ storage: this.config.storage
23
+ });
24
+ }
25
+ async connect() {
26
+ try {
27
+ let accounts = [];
28
+ const isConnected = this.provider.connected;
29
+ if (!isConnected) {
30
+ accounts = await this.provider.request({
31
+ method: 'eth_requestAccounts',
32
+ params: []
33
+ });
34
+ } else {
35
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
36
+ }
37
+ return accounts;
38
+ } catch (error) {
39
+ console.warn('CoinbaseProvider: connect error', error);
40
+ throw error;
41
+ }
42
+ }
43
+ async disconnect() {
44
+ this.provider.disconnect();
45
+ return Promise.resolve();
46
+ }
47
+ request(args) {
48
+ if (!isValidMethod(args.method)) {
49
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
50
+ }
51
+ return this.provider.request(args);
52
+ }
53
+ getChainId() {
54
+ return this.provider.chainId;
55
+ }
56
+ onChainChanged(hexChainId) {
57
+ const chainId = StringUtil.hexToString(hexChainId);
58
+ this.emit('chainChanged', {
59
+ chainId
60
+ });
61
+ }
62
+ on(event, listener) {
63
+ if (event === 'chainChanged') {
64
+ // Create middleware that formats the chain ID before calling the original listener
65
+ const chainChangedMiddleware = hexChainId => {
66
+ const chainId = StringUtil.hexToString(hexChainId);
67
+ listener(chainId);
68
+ };
69
+
70
+ // Store the mapping between original listener and middleware
71
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
72
+ return this.provider.on('chainChanged', chainChangedMiddleware);
73
+ }
74
+ return this.provider.on(event, listener);
75
+ }
76
+ off(event, listener) {
77
+ if (event === 'chainChanged') {
78
+ // Get the middleware wrapper for this listener
79
+ const middleware = this.chainChangedListeners.get(listener);
80
+ if (middleware) {
81
+ // Remove the middleware from the provider
82
+ this.provider.off('chainChanged', middleware);
83
+ // Remove the mapping
84
+ this.chainChangedListeners.delete(listener);
85
+ return this;
86
+ }
87
+ }
88
+ return this.provider.off(event, listener);
89
+ }
90
+ }
91
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["EventEmitter","StringUtil","configure","WalletMobileSDKEVMProvider","isValidMethod","CoinbaseProvider","chainChangedListeners","Map","constructor","config","hostURL","URL","callbackURL","redirect","hostPackageName","provider","jsonRpcUrl","rpcUrl","chainId","defaultChain","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","Error","getChainId","onChainChanged","hexChainId","hexToString","emit","on","event","listener","chainChangedMiddleware","set","off","middleware","get","delete"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ export const COINBASE_METHODS = {
4
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
5
+ SIGN_TRANSACTION: 'eth_signTransaction',
6
+ SEND_TRANSACTION: 'eth_sendTransaction',
7
+ SIGN_MESSAGE: 'personal_sign',
8
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
9
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
10
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
11
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
12
+ WATCH_ASSET: 'wallet_watchAsset'
13
+ };
14
+ export function isValidMethod(method) {
15
+ return Object.values(COINBASE_METHODS).includes(method);
16
+ }
17
+ export function getCoinbaseNamespace(namespaces, accounts) {
18
+ if (!namespaces || !accounts) {
19
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
20
+ }
21
+ const namespace = namespaces['eip155'];
22
+ if (!namespace) {
23
+ throw new Error('CoinbaseConnector: Namespace not found');
24
+ }
25
+ let caipAddresses = [];
26
+ for (const account of accounts) {
27
+ namespace.chains?.forEach(chain => {
28
+ caipAddresses.push(`${chain}:${account}`);
29
+ });
30
+ }
31
+ return {
32
+ ['eip155']: {
33
+ ...namespace,
34
+ methods: Object.values(COINBASE_METHODS),
35
+ accounts: caipAddresses
36
+ }
37
+ };
38
+ }
39
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["COINBASE_METHODS","REQUEST_ACCOUNTS","SIGN_TRANSACTION","SEND_TRANSACTION","SIGN_MESSAGE","SIGN_TYPED_DATA_V3","SIGN_TYPED_DATA_V4","SWITCH_CHAIN","ADD_ETHEREUM_CHAIN","WATCH_ASSET","isValidMethod","method","Object","values","includes","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;AAOA,OAAO,MAAMA,gBAAgB,GAAG;EAC9BC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,YAAY,EAAE,eAAe;EAC7BC,kBAAkB,EAAE,sBAAsB;EAC1CC,kBAAkB,EAAE,sBAAsB;EAC1CC,YAAY,EAAE,4BAA4B;EAC1CC,kBAAkB,EAAE,yBAAyB;EAC7CC,WAAW,EAAE;AACf,CAAU;AAEV,OAAO,SAASC,aAAaA,CAACC,MAAc,EAA4B;EACtE,OAAOC,MAAM,CAACC,MAAM,CAACb,gBAAgB,CAAC,CAACc,QAAQ,CAACH,MAAwB,CAAC;AAC3E;AAEA,OAAO,SAASI,oBAAoBA,CAClCC,UAA+B,EAC/BC,QAAmB,EACP;EACZ,IAAI,CAACD,UAAU,IAAI,CAACC,QAAQ,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,qDAAqD,CAAC;EACxE;EAEA,MAAMC,SAAS,GAAGH,UAAU,CAAC,QAAQ,CAAC;EAEtC,IAAI,CAACG,SAAS,EAAE;IACd,MAAM,IAAID,KAAK,CAAC,wCAAwC,CAAC;EAC3D;EAEA,IAAIE,aAA4B,GAAG,EAAE;EAErC,KAAK,MAAMC,OAAO,IAAIJ,QAAQ,EAAE;IAC9BE,SAAS,CAACG,MAAM,EAAEC,OAAO,CAACC,KAAK,IAAI;MACjCJ,aAAa,CAACK,IAAI,CAAC,GAAGD,KAAK,IAAIH,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEd,MAAM,CAACC,MAAM,CAACb,gBAAgB,CAAC;MACxCiB,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,22 @@
1
+ import { WalletConnector, type AppKitNetwork, type CaipNetworkId, type ConnectionProperties, type ConnectOptions, type ConnectorInitOptions, type Namespaces, type WalletInfo } from '@reown/appkit-common-react-native';
2
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
3
+ import type { CoinbaseConnectorConfig } from '../types';
4
+ export declare class CoinbaseConnector extends WalletConnector {
5
+ private static readonly SUPPORTED_NAMESPACE;
6
+ private config;
7
+ constructor(config?: CoinbaseConnectorConfig);
8
+ init(ops: ConnectorInitOptions): Promise<void>;
9
+ connect(opts?: ConnectOptions): Promise<Namespaces | undefined>;
10
+ disconnect(): Promise<void>;
11
+ getProvider(): CoinbaseProvider;
12
+ getNamespaces(): Namespaces;
13
+ getChainId(): CaipNetworkId | undefined;
14
+ getWalletInfo(): WalletInfo | undefined;
15
+ getProperties(): ConnectionProperties | undefined;
16
+ switchNetwork(network: AppKitNetwork): Promise<void>;
17
+ private deleteSession;
18
+ private saveSession;
19
+ restoreSession(): Promise<boolean>;
20
+ private getStorage;
21
+ }
22
+ //# sourceMappingURL=CoinbaseConnector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoinbaseConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/CoinbaseConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAElB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,UAAU,EAIhB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAmB,MAAM,UAAU,CAAC;AAIzE,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAA4B;IACvE,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,CAAC,EAAE,uBAAuB;IAK7B,IAAI,CAAC,GAAG,EAAE,oBAAoB;IAiB9B,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAU/D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,WAAW,IAAI,gBAAgB;IAQ/B,aAAa,IAAI,UAAU;IAQ3B,UAAU,IAAI,aAAa,GAAG,SAAS;IAOvC,aAAa,IAAI,UAAU,GAAG,SAAS;IASvC,aAAa,IAAI,oBAAoB,GAAG,SAAS;IAI3C,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCnE,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,WAAW;IAKJ,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAajD,OAAO,CAAC,UAAU;CAOnB"}
@@ -0,0 +1,3 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ export type { CoinbaseConnectorConfig } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from 'events';
3
+ import { type Provider, type RequestArguments } from '@reown/appkit-common-react-native';
4
+ import type { CoinbaseProviderConfig } from '../types';
5
+ export declare class CoinbaseProvider extends EventEmitter implements Provider {
6
+ private readonly config;
7
+ private provider;
8
+ private chainChangedListeners;
9
+ constructor(config: CoinbaseProviderConfig);
10
+ connect<T = string[]>(): Promise<T>;
11
+ disconnect(): Promise<void>;
12
+ request<T = unknown>(args: RequestArguments): Promise<T>;
13
+ getChainId(): `0x${string}`;
14
+ onChainChanged(hexChainId: `0x${string}`): void;
15
+ on(event: string, listener: (args?: any) => void): any;
16
+ off(event: string, listener: (args?: any) => void): any;
17
+ }
18
+ //# sourceMappingURL=CoinbaseProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoinbaseProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/CoinbaseProvider.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD,qBAAa,gBAAiB,SAAQ,YAAa,YAAW,QAAQ;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,qBAAqB,CAGzB;gBAEQ,MAAM,EAAE,sBAAsB;IAgBpC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC;IAqBnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAQxD,UAAU,IAAI,KAAK,MAAM,EAAE;IAI3B,cAAc,CAAC,UAAU,EAAE,KAAK,MAAM,EAAE,GAAG,IAAI;IAKtC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;IAiBtD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;CAgBjE"}
@@ -0,0 +1,17 @@
1
+ import type { Namespaces } from '@reown/appkit-common-react-native';
2
+ import type { KVStorage, WalletMobileSDKProviderOptions } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
3
+ import type { COINBASE_METHODS } from './utils';
4
+ export type CoinbaseProviderConfig = Omit<WalletMobileSDKProviderOptions, 'chainId' | 'jsonRpcUrl' | 'address'> & {
5
+ defaultChain?: number;
6
+ redirect: string;
7
+ rpcUrl?: string;
8
+ };
9
+ export type Values<T> = T[keyof T];
10
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
11
+ export type CoinbaseSession = {
12
+ namespaces: Namespaces;
13
+ };
14
+ export type CoinbaseConnectorConfig = {
15
+ storage?: KVStorage;
16
+ };
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,KAAK,EACV,SAAS,EACT,8BAA8B,EAC/B,MAAM,8DAA8D,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,8BAA8B,EAC9B,SAAS,GAAG,YAAY,GAAG,SAAS,CACrC,GAAG;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Namespaces, ProposalNamespaces } from '@reown/appkit-common-react-native';
2
+ import type { CoinbaseMethod } from './types';
3
+ export declare const COINBASE_METHODS: {
4
+ readonly REQUEST_ACCOUNTS: "eth_requestAccounts";
5
+ readonly SIGN_TRANSACTION: "eth_signTransaction";
6
+ readonly SEND_TRANSACTION: "eth_sendTransaction";
7
+ readonly SIGN_MESSAGE: "personal_sign";
8
+ readonly SIGN_TYPED_DATA_V3: "eth_signTypedData_v3";
9
+ readonly SIGN_TYPED_DATA_V4: "eth_signTypedData_v4";
10
+ readonly SWITCH_CHAIN: "wallet_switchEthereumChain";
11
+ readonly ADD_ETHEREUM_CHAIN: "wallet_addEthereumChain";
12
+ readonly WATCH_ASSET: "wallet_watchAsset";
13
+ };
14
+ export declare function isValidMethod(method: string): method is CoinbaseMethod;
15
+ export declare function getCoinbaseNamespace(namespaces?: ProposalNamespaces, accounts?: string[]): Namespaces;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,UAAU,EACV,kBAAkB,EACnB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,gBAAgB;;;;;;;;;;CAUnB,CAAC;AAEX,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,cAAc,CAEtE;AAED,wBAAgB,oBAAoB,CAClC,UAAU,CAAC,EAAE,kBAAkB,EAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,UAAU,CA0BZ"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@reown/appkit-coinbase-react-native",
3
+ "version": "0.0.0-chore-bump-builder-20250728194329",
4
+ "main": "lib/commonjs/index.js",
5
+ "types": "lib/typescript/index.d.ts",
6
+ "module": "lib/module/index.js",
7
+ "source": "src/index.ts",
8
+ "scripts": {
9
+ "build": "bob build",
10
+ "clean": "rm -rf lib",
11
+ "test": "jest --passWithNoTests",
12
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
13
+ },
14
+ "files": [
15
+ "src",
16
+ "lib"
17
+ ],
18
+ "keywords": [
19
+ "web3",
20
+ "crypto",
21
+ "appkit",
22
+ "walletconnect",
23
+ "react-native",
24
+ "coinbase"
25
+ ],
26
+ "repository": "https://github.com/reown-com/appkit-react-native",
27
+ "author": "Reown (https://discord.gg/reown)",
28
+ "homepage": "https://reown.com/appkit",
29
+ "license": "Apache-2.0",
30
+ "bugs": {
31
+ "url": "https://github.com/reown-com/appkit-react-native/issues"
32
+ },
33
+ "publishConfig": {
34
+ "registry": "https://registry.npmjs.org/",
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "@reown/appkit-common-react-native": "0.0.0-chore-bump-builder-20250728194329"
39
+ },
40
+ "peerDependencies": {
41
+ "@coinbase/wallet-mobile-sdk": ">=1.1.2",
42
+ "react": ">=18",
43
+ "react-native": ">=0.72"
44
+ },
45
+ "react-native": "src/index.ts",
46
+ "react-native-builder-bob": {
47
+ "source": "src",
48
+ "output": "lib",
49
+ "targets": [
50
+ "commonjs",
51
+ "module",
52
+ [
53
+ "typescript",
54
+ {
55
+ "tsc": "../../node_modules/.bin/tsc"
56
+ }
57
+ ]
58
+ ]
59
+ },
60
+ "eslintIgnore": [
61
+ "node_modules/",
62
+ "lib/"
63
+ ]
64
+ }
@@ -0,0 +1,163 @@
1
+ import {
2
+ WalletConnector,
3
+ type AppKitNetwork,
4
+ type CaipNetworkId,
5
+ type ChainNamespace,
6
+ type ConnectionProperties,
7
+ type ConnectOptions,
8
+ type ConnectorInitOptions,
9
+ type Namespaces,
10
+ type WalletInfo,
11
+ type Storage,
12
+ NumberUtil,
13
+ StringUtil
14
+ } from '@reown/appkit-common-react-native';
15
+ import { getCoinbaseNamespace } from '../utils';
16
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
17
+ import type { CoinbaseConnectorConfig, CoinbaseSession } from '../types';
18
+
19
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
20
+
21
+ export class CoinbaseConnector extends WalletConnector {
22
+ private static readonly SUPPORTED_NAMESPACE: ChainNamespace = 'eip155';
23
+ private config: CoinbaseConnectorConfig;
24
+
25
+ constructor(config?: CoinbaseConnectorConfig) {
26
+ super({ type: 'coinbase' });
27
+ this.config = config ?? {};
28
+ }
29
+
30
+ override async init(ops: ConnectorInitOptions) {
31
+ super.init(ops);
32
+
33
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
34
+ if (!redirect) {
35
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
36
+ }
37
+
38
+ this.provider = new CoinbaseProvider({
39
+ redirect,
40
+ // use config storage, as it needs to be mmkv-compatible
41
+ storage: this.config.storage
42
+ });
43
+
44
+ await this.restoreSession();
45
+ }
46
+
47
+ override async connect(opts?: ConnectOptions): Promise<Namespaces | undefined> {
48
+ const accounts = await this.getProvider().connect();
49
+
50
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
51
+ this.namespaces = namespaces;
52
+ this.saveSession(namespaces);
53
+
54
+ return this.namespaces;
55
+ }
56
+
57
+ override async disconnect(): Promise<void> {
58
+ await super.disconnect();
59
+ this.deleteSession();
60
+ }
61
+
62
+ override getProvider(): CoinbaseProvider {
63
+ if (!this.provider) {
64
+ throw new Error('CoinbaseConnector: Provider not initialized');
65
+ }
66
+
67
+ return this.provider as CoinbaseProvider;
68
+ }
69
+
70
+ override getNamespaces(): Namespaces {
71
+ if (!this.namespaces) {
72
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
73
+ }
74
+
75
+ return this.namespaces;
76
+ }
77
+
78
+ override getChainId(): CaipNetworkId | undefined {
79
+ const hexChainId = this.getProvider().getChainId();
80
+ const chainId = StringUtil.hexToString(hexChainId);
81
+
82
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}` as CaipNetworkId;
83
+ }
84
+
85
+ override getWalletInfo(): WalletInfo | undefined {
86
+ // TODO: Add icon
87
+ return {
88
+ name: 'Coinbase Wallet',
89
+ description: 'Your home to everything onchain',
90
+ url: 'https://www.coinbase.com/wallet'
91
+ };
92
+ }
93
+
94
+ override getProperties(): ConnectionProperties | undefined {
95
+ return undefined;
96
+ }
97
+
98
+ override async switchNetwork(network: AppKitNetwork): Promise<void> {
99
+ const provider = this.getProvider();
100
+ const chainId_ = NumberUtil.convertNumericToHexString(network.id);
101
+
102
+ try {
103
+ await provider.request({
104
+ method: 'wallet_switchEthereumChain',
105
+ params: [{ chainId: chainId_ }]
106
+ });
107
+ } catch (error: any) {
108
+ // Indicates chain is not added to provider
109
+ if (error?.code === 4902) {
110
+ try {
111
+ await provider.request({
112
+ method: 'wallet_addEthereumChain',
113
+ params: [
114
+ {
115
+ chainId: chainId_,
116
+ chainName: network.name,
117
+ nativeCurrency: network.nativeCurrency,
118
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
119
+ blockExplorerUrls: [network.blockExplorers?.default.url]
120
+ }
121
+ ]
122
+ });
123
+ } catch (e) {
124
+ console.warn('CoinbaseConnector: switchNetwork error', e);
125
+ throw e;
126
+ }
127
+ }
128
+ console.warn('CoinbaseConnector: switchNetwork error', error);
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ private deleteSession(): void {
134
+ const storage = this.getStorage();
135
+ storage.removeItem(SESSION_KEY);
136
+ }
137
+
138
+ private saveSession(namespaces: Namespaces): void {
139
+ const storage = this.getStorage();
140
+ storage.setItem<CoinbaseSession>(SESSION_KEY, { namespaces });
141
+ }
142
+
143
+ override async restoreSession(): Promise<boolean> {
144
+ const storage = this.getStorage();
145
+ const session = await storage.getItem<CoinbaseSession>(SESSION_KEY);
146
+ if (!session) {
147
+ return false;
148
+ }
149
+
150
+ const { namespaces } = session;
151
+ this.namespaces = namespaces;
152
+
153
+ return true;
154
+ }
155
+
156
+ private getStorage(): Storage {
157
+ if (!this.storage) {
158
+ throw new Error('CoinbaseConnector: Storage not initialized');
159
+ }
160
+
161
+ return this.storage;
162
+ }
163
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ export type { CoinbaseConnectorConfig } from './types';
@@ -0,0 +1,112 @@
1
+ import EventEmitter from 'events';
2
+ import {
3
+ type Provider,
4
+ type RequestArguments,
5
+ StringUtil
6
+ } from '@reown/appkit-common-react-native';
7
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
8
+ import { isValidMethod } from '../utils';
9
+ import type { CoinbaseProviderConfig } from '../types';
10
+
11
+ export class CoinbaseProvider extends EventEmitter implements Provider {
12
+ private readonly config: CoinbaseProviderConfig;
13
+ private provider: WalletMobileSDKEVMProvider;
14
+ private chainChangedListeners = new Map<
15
+ (args?: any) => void,
16
+ (hexChainId: `0x${string}`) => void
17
+ >();
18
+
19
+ constructor(config: CoinbaseProviderConfig) {
20
+ super();
21
+ this.config = config;
22
+ configure({
23
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
24
+ callbackURL: new URL(this.config.redirect), // App Universal Link
25
+ hostPackageName: 'org.toshi'
26
+ });
27
+ this.provider = new WalletMobileSDKEVMProvider({
28
+ ...this.config,
29
+ jsonRpcUrl: this.config.rpcUrl,
30
+ chainId: this.config.defaultChain,
31
+ storage: this.config.storage
32
+ });
33
+ }
34
+
35
+ async connect<T = string[]>(): Promise<T> {
36
+ try {
37
+ let accounts: string[] = [];
38
+ const isConnected = this.provider.connected;
39
+
40
+ if (!isConnected) {
41
+ accounts = await this.provider.request({
42
+ method: 'eth_requestAccounts',
43
+ params: []
44
+ });
45
+ } else {
46
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
47
+ }
48
+
49
+ return accounts as T;
50
+ } catch (error) {
51
+ console.warn('CoinbaseProvider: connect error', error);
52
+
53
+ throw error;
54
+ }
55
+ }
56
+ async disconnect(): Promise<void> {
57
+ this.provider.disconnect();
58
+
59
+ return Promise.resolve();
60
+ }
61
+
62
+ request<T = unknown>(args: RequestArguments): Promise<T> {
63
+ if (!isValidMethod(args.method)) {
64
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
65
+ }
66
+
67
+ return this.provider.request(args);
68
+ }
69
+
70
+ getChainId(): `0x${string}` {
71
+ return this.provider.chainId as `0x${string}`;
72
+ }
73
+
74
+ onChainChanged(hexChainId: `0x${string}`): void {
75
+ const chainId = StringUtil.hexToString(hexChainId);
76
+ this.emit('chainChanged', { chainId });
77
+ }
78
+
79
+ override on(event: string, listener: (args?: any) => void): any {
80
+ if (event === 'chainChanged') {
81
+ // Create middleware that formats the chain ID before calling the original listener
82
+ const chainChangedMiddleware = (hexChainId: `0x${string}`) => {
83
+ const chainId = StringUtil.hexToString(hexChainId);
84
+ listener(chainId);
85
+ };
86
+
87
+ // Store the mapping between original listener and middleware
88
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
89
+
90
+ return this.provider.on('chainChanged', chainChangedMiddleware);
91
+ }
92
+
93
+ return this.provider.on(event, listener);
94
+ }
95
+
96
+ override off(event: string, listener: (args?: any) => void): any {
97
+ if (event === 'chainChanged') {
98
+ // Get the middleware wrapper for this listener
99
+ const middleware = this.chainChangedListeners.get(listener);
100
+ if (middleware) {
101
+ // Remove the middleware from the provider
102
+ this.provider.off('chainChanged', middleware);
103
+ // Remove the mapping
104
+ this.chainChangedListeners.delete(listener);
105
+
106
+ return this;
107
+ }
108
+ }
109
+
110
+ return this.provider.off(event, listener);
111
+ }
112
+ }
package/src/types.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { Namespaces } from '@reown/appkit-common-react-native';
2
+ import type {
3
+ KVStorage,
4
+ WalletMobileSDKProviderOptions
5
+ } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
6
+ import type { COINBASE_METHODS } from './utils';
7
+
8
+ export type CoinbaseProviderConfig = Omit<
9
+ WalletMobileSDKProviderOptions,
10
+ 'chainId' | 'jsonRpcUrl' | 'address'
11
+ > & {
12
+ defaultChain?: number;
13
+ redirect: string;
14
+ rpcUrl?: string;
15
+ };
16
+
17
+ export type Values<T> = T[keyof T];
18
+
19
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
20
+
21
+ export type CoinbaseSession = {
22
+ namespaces: Namespaces;
23
+ };
24
+
25
+ export type CoinbaseConnectorConfig = {
26
+ storage?: KVStorage;
27
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type {
2
+ CaipAddress,
3
+ Namespaces,
4
+ ProposalNamespaces
5
+ } from '@reown/appkit-common-react-native';
6
+ import type { CoinbaseMethod } from './types';
7
+
8
+ export const COINBASE_METHODS = {
9
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
10
+ SIGN_TRANSACTION: 'eth_signTransaction',
11
+ SEND_TRANSACTION: 'eth_sendTransaction',
12
+ SIGN_MESSAGE: 'personal_sign',
13
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
14
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
15
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
16
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
17
+ WATCH_ASSET: 'wallet_watchAsset'
18
+ } as const;
19
+
20
+ export function isValidMethod(method: string): method is CoinbaseMethod {
21
+ return Object.values(COINBASE_METHODS).includes(method as CoinbaseMethod);
22
+ }
23
+
24
+ export function getCoinbaseNamespace(
25
+ namespaces?: ProposalNamespaces,
26
+ accounts?: string[]
27
+ ): Namespaces {
28
+ if (!namespaces || !accounts) {
29
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
30
+ }
31
+
32
+ const namespace = namespaces['eip155'];
33
+
34
+ if (!namespace) {
35
+ throw new Error('CoinbaseConnector: Namespace not found');
36
+ }
37
+
38
+ let caipAddresses: CaipAddress[] = [];
39
+
40
+ for (const account of accounts) {
41
+ namespace.chains?.forEach(chain => {
42
+ caipAddresses.push(`${chain}:${account}`);
43
+ });
44
+ }
45
+
46
+ return {
47
+ ['eip155']: {
48
+ ...namespace,
49
+ methods: Object.values(COINBASE_METHODS),
50
+ accounts: caipAddresses
51
+ }
52
+ };
53
+ }