@multiplatform.one/web3 7.24.0 → 7.25.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.
- package/README.md +33 -0
- package/dist/cjs/bridge/AuthBridge.cjs +124 -0
- package/dist/cjs/bridge/AuthBridge.native.js +186 -0
- package/dist/cjs/bridge/AuthBridge.native.js.map +1 -0
- package/dist/cjs/bridge/BridgeClient.cjs +12 -9
- package/dist/cjs/bridge/BridgeClient.native.js +17 -12
- package/dist/cjs/bridge/BridgeClient.native.js.map +1 -1
- package/dist/cjs/bridge/BridgeHost.cjs +11 -3
- package/dist/cjs/bridge/BridgeHost.native.js +11 -3
- package/dist/cjs/bridge/BridgeHost.native.js.map +1 -1
- package/dist/cjs/bridge/GpgBridge.cjs +61 -0
- package/dist/cjs/bridge/GpgBridge.native.js +111 -0
- package/dist/cjs/bridge/GpgBridge.native.js.map +1 -0
- package/dist/cjs/bridge/SuiBridge.cjs +51 -0
- package/dist/cjs/bridge/SuiBridge.native.js +99 -0
- package/dist/cjs/bridge/SuiBridge.native.js.map +1 -0
- package/dist/cjs/bridge/authTypes.cjs +28 -0
- package/dist/cjs/bridge/authTypes.native.js +31 -0
- package/dist/cjs/bridge/authTypes.native.js.map +1 -0
- package/dist/cjs/bridge/core.cjs +65 -0
- package/dist/cjs/bridge/core.native.js +68 -0
- package/dist/cjs/bridge/core.native.js.map +1 -0
- package/dist/cjs/bridge/hosting.cjs +91 -0
- package/dist/cjs/bridge/hosting.native.js +117 -0
- package/dist/cjs/bridge/hosting.native.js.map +1 -0
- package/dist/cjs/bridge/index.cjs +3 -17
- package/dist/cjs/bridge/index.native.js +2 -16
- package/dist/cjs/bridge/index.native.js.map +1 -1
- package/dist/cjs/bridge/nativeHost.cjs +91 -0
- package/dist/cjs/bridge/nativeHost.native.js +118 -0
- package/dist/cjs/bridge/nativeHost.native.js.map +1 -0
- package/dist/cjs/bridge/protocol.cjs +30 -1
- package/dist/cjs/bridge/protocol.native.js +147 -1
- package/dist/cjs/bridge/protocol.native.js.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.native.js +1 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/providers/WalletProvider.cjs +2 -0
- package/dist/cjs/providers/WalletProvider.native.js +123 -90
- package/dist/cjs/providers/WalletProvider.native.js.map +1 -1
- package/dist/cjs/providers/index.cjs +1 -0
- package/dist/cjs/providers/index.native.js +1 -0
- package/dist/cjs/providers/index.native.js.map +1 -1
- package/dist/cjs/providers/native/deepLink.cjs +40 -23
- package/dist/cjs/providers/native/deepLink.native.js +43 -25
- package/dist/cjs/providers/native/deepLink.native.js.map +1 -1
- package/dist/cjs/providers/native/inject.cjs +2 -4
- package/dist/cjs/providers/native/inject.native.js +2 -4
- package/dist/cjs/providers/native/inject.native.js.map +1 -1
- package/dist/cjs/providers/walletBridge.cjs +35 -0
- package/dist/cjs/providers/walletBridge.native.js +38 -0
- package/dist/cjs/providers/walletBridge.native.js.map +1 -0
- package/dist/cjs/providers/walletConfig.native.js.map +1 -1
- package/dist/esm/bridge/AuthBridge.mjs +99 -0
- package/dist/esm/bridge/AuthBridge.mjs.map +1 -0
- package/dist/esm/bridge/AuthBridge.native.js +158 -0
- package/dist/esm/bridge/AuthBridge.native.js.map +1 -0
- package/dist/esm/bridge/BridgeClient.mjs +13 -10
- package/dist/esm/bridge/BridgeClient.mjs.map +1 -1
- package/dist/esm/bridge/BridgeClient.native.js +18 -13
- package/dist/esm/bridge/BridgeClient.native.js.map +1 -1
- package/dist/esm/bridge/BridgeHost.mjs +12 -4
- package/dist/esm/bridge/BridgeHost.mjs.map +1 -1
- package/dist/esm/bridge/BridgeHost.native.js +12 -4
- package/dist/esm/bridge/BridgeHost.native.js.map +1 -1
- package/dist/esm/bridge/GpgBridge.mjs +36 -0
- package/dist/esm/bridge/GpgBridge.mjs.map +1 -0
- package/dist/esm/bridge/GpgBridge.native.js +83 -0
- package/dist/esm/bridge/GpgBridge.native.js.map +1 -0
- package/dist/esm/bridge/SuiBridge.mjs +26 -0
- package/dist/esm/bridge/SuiBridge.mjs.map +1 -0
- package/dist/esm/bridge/SuiBridge.native.js +71 -0
- package/dist/esm/bridge/SuiBridge.native.js.map +1 -0
- package/dist/esm/bridge/authTypes.mjs +3 -0
- package/dist/esm/bridge/authTypes.mjs.map +1 -0
- package/dist/esm/bridge/authTypes.native.js +3 -0
- package/dist/esm/bridge/authTypes.native.js.map +1 -0
- package/dist/esm/bridge/core.mjs +17 -0
- package/dist/esm/bridge/core.mjs.map +1 -0
- package/dist/esm/bridge/core.native.js +17 -0
- package/dist/esm/bridge/core.native.js.map +1 -0
- package/dist/esm/bridge/hosting.mjs +62 -0
- package/dist/esm/bridge/hosting.mjs.map +1 -0
- package/dist/esm/bridge/hosting.native.js +85 -0
- package/dist/esm/bridge/hosting.native.js.map +1 -0
- package/dist/esm/bridge/index.mjs +2 -9
- package/dist/esm/bridge/index.mjs.map +1 -1
- package/dist/esm/bridge/index.native.js +2 -9
- package/dist/esm/bridge/index.native.js.map +1 -1
- package/dist/esm/bridge/nativeHost.mjs +65 -0
- package/dist/esm/bridge/nativeHost.mjs.map +1 -0
- package/dist/esm/bridge/nativeHost.native.js +89 -0
- package/dist/esm/bridge/nativeHost.native.js.map +1 -0
- package/dist/esm/bridge/protocol.mjs +28 -2
- package/dist/esm/bridge/protocol.mjs.map +1 -1
- package/dist/esm/bridge/protocol.native.js +145 -2
- package/dist/esm/bridge/protocol.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -2
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/providers/WalletProvider.mjs +2 -1
- package/dist/esm/providers/WalletProvider.mjs.map +1 -1
- package/dist/esm/providers/WalletProvider.native.js +125 -93
- package/dist/esm/providers/WalletProvider.native.js.map +1 -1
- package/dist/esm/providers/index.mjs +2 -2
- package/dist/esm/providers/index.mjs.map +1 -1
- package/dist/esm/providers/index.native.js +2 -2
- package/dist/esm/providers/index.native.js.map +1 -1
- package/dist/esm/providers/native/deepLink.mjs +36 -24
- package/dist/esm/providers/native/deepLink.mjs.map +1 -1
- package/dist/esm/providers/native/deepLink.native.js +39 -26
- package/dist/esm/providers/native/deepLink.native.js.map +1 -1
- package/dist/esm/providers/native/inject.mjs +1 -3
- package/dist/esm/providers/native/inject.mjs.map +1 -1
- package/dist/esm/providers/native/inject.native.js +1 -3
- package/dist/esm/providers/native/inject.native.js.map +1 -1
- package/dist/esm/providers/walletBridge.mjs +9 -0
- package/dist/esm/providers/walletBridge.mjs.map +1 -0
- package/dist/esm/providers/walletBridge.native.js +9 -0
- package/dist/esm/providers/walletBridge.native.js.map +1 -0
- package/dist/esm/providers/walletConfig.mjs.map +1 -1
- package/dist/esm/providers/walletConfig.native.js.map +1 -1
- package/dist/jsx/bridge/AuthBridge.mjs +99 -0
- package/dist/jsx/bridge/AuthBridge.mjs.map +1 -0
- package/dist/jsx/bridge/AuthBridge.native.js +186 -0
- package/dist/jsx/bridge/AuthBridge.native.js.map +1 -0
- package/dist/jsx/bridge/BridgeClient.mjs +13 -10
- package/dist/jsx/bridge/BridgeClient.mjs.map +1 -1
- package/dist/jsx/bridge/BridgeClient.native.js +17 -12
- package/dist/jsx/bridge/BridgeClient.native.js.map +1 -1
- package/dist/jsx/bridge/BridgeHost.mjs +12 -4
- package/dist/jsx/bridge/BridgeHost.mjs.map +1 -1
- package/dist/jsx/bridge/BridgeHost.native.js +11 -3
- package/dist/jsx/bridge/BridgeHost.native.js.map +1 -1
- package/dist/jsx/bridge/GpgBridge.mjs +36 -0
- package/dist/jsx/bridge/GpgBridge.mjs.map +1 -0
- package/dist/jsx/bridge/GpgBridge.native.js +111 -0
- package/dist/jsx/bridge/GpgBridge.native.js.map +1 -0
- package/dist/jsx/bridge/SuiBridge.mjs +26 -0
- package/dist/jsx/bridge/SuiBridge.mjs.map +1 -0
- package/dist/jsx/bridge/SuiBridge.native.js +99 -0
- package/dist/jsx/bridge/SuiBridge.native.js.map +1 -0
- package/dist/jsx/bridge/authTypes.mjs +3 -0
- package/dist/jsx/bridge/authTypes.mjs.map +1 -0
- package/dist/jsx/bridge/authTypes.native.js +31 -0
- package/dist/jsx/bridge/authTypes.native.js.map +1 -0
- package/dist/jsx/bridge/core.mjs +17 -0
- package/dist/jsx/bridge/core.mjs.map +1 -0
- package/dist/jsx/bridge/core.native.js +68 -0
- package/dist/jsx/bridge/core.native.js.map +1 -0
- package/dist/jsx/bridge/hosting.mjs +62 -0
- package/dist/jsx/bridge/hosting.mjs.map +1 -0
- package/dist/jsx/bridge/hosting.native.js +117 -0
- package/dist/jsx/bridge/hosting.native.js.map +1 -0
- package/dist/jsx/bridge/index.mjs +2 -9
- package/dist/jsx/bridge/index.mjs.map +1 -1
- package/dist/jsx/bridge/index.native.js +2 -16
- package/dist/jsx/bridge/index.native.js.map +1 -1
- package/dist/jsx/bridge/nativeHost.mjs +65 -0
- package/dist/jsx/bridge/nativeHost.mjs.map +1 -0
- package/dist/jsx/bridge/nativeHost.native.js +118 -0
- package/dist/jsx/bridge/nativeHost.native.js.map +1 -0
- package/dist/jsx/bridge/protocol.mjs +28 -2
- package/dist/jsx/bridge/protocol.mjs.map +1 -1
- package/dist/jsx/bridge/protocol.native.js +147 -1
- package/dist/jsx/bridge/protocol.native.js.map +1 -1
- package/dist/jsx/index.js +2 -2
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -2
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +1 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/providers/WalletProvider.mjs +2 -1
- package/dist/jsx/providers/WalletProvider.mjs.map +1 -1
- package/dist/jsx/providers/WalletProvider.native.js +123 -90
- package/dist/jsx/providers/WalletProvider.native.js.map +1 -1
- package/dist/jsx/providers/index.mjs +2 -2
- package/dist/jsx/providers/index.mjs.map +1 -1
- package/dist/jsx/providers/index.native.js +1 -0
- package/dist/jsx/providers/index.native.js.map +1 -1
- package/dist/jsx/providers/native/deepLink.mjs +36 -24
- package/dist/jsx/providers/native/deepLink.mjs.map +1 -1
- package/dist/jsx/providers/native/deepLink.native.js +43 -25
- package/dist/jsx/providers/native/deepLink.native.js.map +1 -1
- package/dist/jsx/providers/native/inject.mjs +1 -3
- package/dist/jsx/providers/native/inject.mjs.map +1 -1
- package/dist/jsx/providers/native/inject.native.js +2 -4
- package/dist/jsx/providers/native/inject.native.js.map +1 -1
- package/dist/jsx/providers/walletBridge.mjs +9 -0
- package/dist/jsx/providers/walletBridge.mjs.map +1 -0
- package/dist/jsx/providers/walletBridge.native.js +38 -0
- package/dist/jsx/providers/walletBridge.native.js.map +1 -0
- package/dist/jsx/providers/walletConfig.mjs.map +1 -1
- package/dist/jsx/providers/walletConfig.native.js.map +1 -1
- package/docs/bridge-protocol.md +485 -0
- package/package.json +14 -6
- package/src/bridge/AuthBridge.ts +146 -0
- package/src/bridge/BridgeClient.spec.ts +12 -0
- package/src/bridge/BridgeClient.ts +15 -10
- package/src/bridge/BridgeHost.spec.ts +20 -4
- package/src/bridge/BridgeHost.ts +16 -5
- package/src/bridge/GpgBridge.ts +49 -0
- package/src/bridge/SuiBridge.ts +34 -0
- package/src/bridge/authTypes.ts +76 -0
- package/src/bridge/core.ts +42 -0
- package/src/bridge/hosting.spec.ts +98 -0
- package/src/bridge/hosting.ts +99 -0
- package/src/bridge/index.ts +1 -8
- package/src/bridge/nativeHost.spec.ts +165 -0
- package/src/bridge/nativeHost.ts +120 -0
- package/src/bridge/protocol.spec.ts +24 -1
- package/src/bridge/protocol.ts +44 -1
- package/src/index.ts +2 -0
- package/src/providers/WalletProvider.native.tsx +139 -85
- package/src/providers/WalletProvider.tsx +1 -1
- package/src/providers/index.ts +2 -0
- package/src/providers/native/deepLink.spec.ts +73 -1
- package/src/providers/native/deepLink.ts +76 -28
- package/src/providers/native/inject.ts +1 -9
- package/src/providers/walletBridge.ts +24 -0
- package/src/providers/walletConfig.ts +15 -1
- package/types/bridge/AuthBridge.d.ts +58 -0
- package/types/bridge/AuthBridge.d.ts.map +1 -0
- package/types/bridge/BridgeClient.d.ts +3 -1
- package/types/bridge/BridgeClient.d.ts.map +1 -1
- package/types/bridge/BridgeHost.d.ts +1 -1
- package/types/bridge/BridgeHost.d.ts.map +1 -1
- package/types/bridge/GpgBridge.d.ts +23 -0
- package/types/bridge/GpgBridge.d.ts.map +1 -0
- package/types/bridge/SuiBridge.d.ts +18 -0
- package/types/bridge/SuiBridge.d.ts.map +1 -0
- package/types/bridge/authTypes.d.ts +71 -0
- package/types/bridge/authTypes.d.ts.map +1 -0
- package/types/bridge/core.d.ts +16 -0
- package/types/bridge/core.d.ts.map +1 -0
- package/types/bridge/hosting.d.ts +34 -0
- package/types/bridge/hosting.d.ts.map +1 -0
- package/types/bridge/index.d.ts +1 -8
- package/types/bridge/index.d.ts.map +1 -1
- package/types/bridge/nativeHost.d.ts +55 -0
- package/types/bridge/nativeHost.d.ts.map +1 -0
- package/types/bridge/protocol.d.ts +34 -1
- package/types/bridge/protocol.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/providers/WalletProvider.d.ts +1 -0
- package/types/providers/WalletProvider.d.ts.map +1 -1
- package/types/providers/WalletProvider.native.d.ts +2 -1
- package/types/providers/WalletProvider.native.d.ts.map +1 -1
- package/types/providers/index.d.ts +1 -1
- package/types/providers/index.d.ts.map +1 -1
- package/types/providers/native/deepLink.d.ts +29 -4
- package/types/providers/native/deepLink.d.ts.map +1 -1
- package/types/providers/native/inject.d.ts +1 -7
- package/types/providers/native/inject.d.ts.map +1 -1
- package/types/providers/walletBridge.d.ts +17 -0
- package/types/providers/walletBridge.d.ts.map +1 -0
- package/types/providers/walletConfig.d.ts +18 -1
- package/types/providers/walletConfig.d.ts.map +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
const WalletBridgeContext = createContext(null);
|
|
3
|
+
function useWalletBridge() {
|
|
4
|
+
const value = useContext(WalletBridgeContext);
|
|
5
|
+
if (!value) throw new Error("useWalletBridge must be used within a native WalletProvider");
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
export { WalletBridgeContext, useWalletBridge };
|
|
9
|
+
//# sourceMappingURL=walletBridge.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createContext","useContext","WalletBridgeContext","useWalletBridge","value","Error"],"sources":["../../../src/providers/walletBridge.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,aAAA,EAAeC,UAAA,QAAkB;AAgBnC,MAAMC,mBAAA,GAAsBF,aAAA,CAA+C,IAAI;AAG/E,SAASG,gBAAA,EAA4C;EAC1D,MAAMC,KAAA,GAAQH,UAAA,CAAWC,mBAAmB;EAC5C,IAAI,CAACE,KAAA,EAAO,MAAM,IAAIC,KAAA,CAAM,6DAA6D;EACzF,OAAOD,KAAA;AACT","ignoreList":[]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
}), mod);
|
|
25
|
+
var walletBridge_exports = {};
|
|
26
|
+
__export(walletBridge_exports, {
|
|
27
|
+
WalletBridgeContext: () => WalletBridgeContext,
|
|
28
|
+
useWalletBridge: () => useWalletBridge
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(walletBridge_exports);
|
|
31
|
+
var import_react = require("react");
|
|
32
|
+
var WalletBridgeContext = (0, import_react.createContext)(null);
|
|
33
|
+
function useWalletBridge() {
|
|
34
|
+
var value = (0, import_react.useContext)(WalletBridgeContext);
|
|
35
|
+
if (!value) throw new Error("useWalletBridge must be used within a native WalletProvider");
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=walletBridge.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name"],"sources":["../../../src/providers/walletBridge.ts"],"sourcesContent":[null],"mappings":"AAAA,YAAS;;AAgBF,IAAAA,SAAM,GAAAC,MAAA,CAAAC,cAAsB;AAG5B,IAAAC,gBAAS,GAAAF,MAA4C,CAAAG,wBAAA;AAC1D,IAAAC,iBAAc,GAAAJ,MAAW,CAAAK,mBAAmB;AAC5C,IAAAC,YAAY,GAAAN,MAAU,CAAAO,SAAM,CAAAC,cAAA;AAC5B,IAAAC,QAAO,GAAAA,CAAAC,MAAA,EAAAC,GAAA;EACT,SAAAC,IAAA,IAAAD,GAAA,E","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createContext","useContext","arbitrum","base","hardhat","mainnet","optimism","polygon","sepolia","defaultChains","resolveChains","config","chains","enableTestnets","localnet","localnetRpcUrl","active","filter","chain","testnet","length","local","rpcUrls","default","http","id","Web3ConfigContext","useWeb3Config","Error"],"sources":["../../../src/providers/walletConfig.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,aAAA,EAAeC,UAAA,QAAkB;AAE1C,SAASC,QAAA,EAAUC,IAAA,EAAMC,OAAA,EAASC,OAAA,EAASC,QAAA,EAAUC,OAAA,EAASC,OAAA,QAAe;
|
|
1
|
+
{"version":3,"names":["createContext","useContext","arbitrum","base","hardhat","mainnet","optimism","polygon","sepolia","defaultChains","resolveChains","config","chains","enableTestnets","localnet","localnetRpcUrl","active","filter","chain","testnet","length","local","rpcUrls","default","http","id","Web3ConfigContext","useWeb3Config","Error"],"sources":["../../../src/providers/walletConfig.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,aAAA,EAAeC,UAAA,QAAkB;AAE1C,SAASC,QAAA,EAAUC,IAAA,EAAMC,OAAA,EAASC,OAAA,EAASC,QAAA,EAAUC,OAAA,EAASC,OAAA,QAAe;AAStE,MAAMC,aAAA,GAA8C,CACzDJ,OAAA,EACAE,OAAA,EACAD,QAAA,EACAJ,QAAA,EACAC,IAAA,EACAK,OAAA,CACF;AAmDO,SAASE,cAAcC,MAAA,EAAkD;EAC9E,MAAM;IACJC,MAAA,GAASH,aAAA;IACTI,cAAA,GAAiB;IACjBC,QAAA,GAAW;IACXC;EACF,IAAIJ,MAAA;EACJ,IAAIK,MAAA,GAAkBH,cAAA,GAAiB,CAAC,GAAGD,MAAM,IAAIA,MAAA,CAAOK,MAAA,CAAQC,KAAA,IAAU,CAACA,KAAA,CAAMC,OAAO;EAC5F,IAAIH,MAAA,CAAOI,MAAA,KAAW,GAAGJ,MAAA,GAAS,CAAC,GAAGJ,MAAM;EAC5C,IAAIE,QAAA,EAAU;IACZ,MAAMO,KAAA,GAAeN,cAAA,GACjB;MAAE,GAAGX,OAAA;MAASkB,OAAA,EAAS;QAAEC,OAAA,EAAS;UAAEC,IAAA,EAAM,CAACT,cAAc;QAAE;MAAE;IAAE,IAC/DX,OAAA;IACJY,MAAA,GAAS,CAACK,KAAA,EAAO,GAAGL,MAAA,CAAOC,MAAA,CAAQC,KAAA,IAAUA,KAAA,CAAMO,EAAA,KAAOrB,OAAA,CAAQqB,EAAE,CAAC;EACvE;EACA,OAAOT,MAAA;AACT;AAEO,MAAMU,iBAAA,GAAoB1B,aAAA,CAAiC,IAAI;AAE/D,SAAS2B,cAAA,EAA4B;EAC1C,MAAMhB,MAAA,GAASV,UAAA,CAAWyB,iBAAiB;EAC3C,IAAI,CAACf,MAAA,EAAQ;IACX,MAAM,IAAIiB,KAAA,CAAM,oDAAoD;EACtE;EACA,OAAOjB,MAAA;AACT","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toCommonJS","mod","value","walletConfig_exports","Web3ConfigContext","defaultChains","resolveChains","useWeb3Config","module","exports","import_react","require","import_chains","mainnet","polygon","optimism","arbitrum"],"sources":["../../../src/providers/walletConfig.ts"],"sourcesContent":[null],"mappings":"AAAA,YAAS;;AAET,IAAAA,SAAS,GAAAC,MAAU,CAAAC,cAAe;
|
|
1
|
+
{"version":3,"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toCommonJS","mod","value","walletConfig_exports","Web3ConfigContext","defaultChains","resolveChains","useWeb3Config","module","exports","import_react","require","import_chains","mainnet","polygon","optimism","arbitrum"],"sources":["../../../src/providers/walletConfig.ts"],"sourcesContent":[null],"mappings":"AAAA,YAAS;;AAET,IAAAA,SAAS,GAAAC,MAAU,CAAAC,cAAe;AAS3B,IAAAC,gBAAM,GAA8CF,MAAA,CAAAG,wBAAA;AAAA,IACzDC,iBAAA,GAAAJ,MAAA,CAAAK,mBAAA;AAAA,IACAC,YAAA,GAAAN,MAAA,CAAAO,SAAA,CAAAC,cAAA;AAAA,IACAC,QAAA,GAAAA,CAAAC,MAAA,EAAAC,GAAA;EACA,SAAAC,IAAA,IAAAD,GAAA,EACAZ,SAAA,CAAAW,MAAA,EAAAE,IAAA;IAAAC,GAAA,EAAAF,GAAA,CAAAC,IAAA;IAAAE,UAAA;EAAA;AAAA;AAEF,IAAAC,WAAA,GAAAA,CAAAC,EAAA,EAAAC,IAAA,EAAAC,MAAA,EAAAC,IAAA;EAmDO,IAAAF,IAAS,WAAAA,IAAc,aAAkD,WAAAA,IAAA;IAC9E,KAAM,IAAAG,GAAA,IAAAhB,iBAAA,CAAAa,IAAA,GACJ,KAAAX,YAAS,CAAAe,IAAA,CAAAL,EAAA,EAAAI,GAAA,KAAAA,GAAA,KAAAF,MAAA,EACTnB,SAAA,CAAAiB,EAAA,EAAiBI,GAAA;MAAAP,GAAA,EAAAA,CAAA,KAAAI,IAAA,CAAAG,GAAA;MAAAN,UAAA,IAAAK,IAAA,GAAAjB,gBAAA,CAAAe,IAAA,EAAAG,GAAA,MAAAD,IAAA,CAAAL;IAAA;EAAA;EACN,OACXE,EAAA;AAAA;AAEF,IAAAM,YAAsB,GAAAC,GAAA,IAAAR,WAAqB,CAAAhB,SAAU,KAAO,YAAQ;EAAAyB,KAAW;AAAM,IAAOD,GAAA;AAC5F,IAAAE,oBAAsB,GAAG;AACzBhB,QAAI,CAAAgB,oBAAU;EACZC,iBAAqB,EAAAA,CAAA,KAAAA,iBACZ;EAETC,aAAU,EAAAA,CAAA,KAAOA,aAAU;EAC7BC,aAAA,EAAAA,CAAA,KAAAA,aAAA;EACAC,aAAO,EAAAA,CAAA,KAAAA;AACT;AAEOC,MAAM,CAAAC,OAAA,GAAAT,YAAoB,CAAAG,oBAAqC;AAE/D,IAAAO,YAAS,GAAAC,OAA4B;AAC1C,IAAAC,aAAe,GAAAD,OAAA,CAAW;AAC1B,IAAAN,aAAa,IACXO,aAAU,CAAAC,OAAM,EAClBD,aAAA,CAAAE,OAAA,EACAF,aAAO,CAAAG,QAAA,EACTH,aAAA,CAAAI,QAAA,E","ignoreList":[]}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
# mpo web3 WebView bridge protocol
|
|
2
|
+
|
|
3
|
+
Protocol version: 1
|
|
4
|
+
|
|
5
|
+
A native app shows mpo web3's wallet UI by loading a hosted web page in a
|
|
6
|
+
WebView and talking to it through JSON messages. The page owns every wallet
|
|
7
|
+
and chain interaction: the connect modal, MetaMask Connect, Phantom, the
|
|
8
|
+
Sui and GPG signers, and the Keycloak wallet sign-in. The app never links a
|
|
9
|
+
wallet SDK. This document is the whole contract, so a Kotlin or Swift host can
|
|
10
|
+
implement it without reading the TypeScript. The React Native host in
|
|
11
|
+
`src/providers/WalletProvider.native.tsx` and `src/bridge/nativeHost.ts` is one
|
|
12
|
+
implementation of it.
|
|
13
|
+
|
|
14
|
+
Terms: the **host** is the native app, the **page** is the hosted
|
|
15
|
+
`webview.html` running inside the host's WebView.
|
|
16
|
+
|
|
17
|
+
## 1. The page must be hosted
|
|
18
|
+
|
|
19
|
+
Serve `@multiplatform.one/web3/assets/webview.html` over https and load it
|
|
20
|
+
by URL. Never load it from `file:`, `data:`, an asset loader or inline HTML.
|
|
21
|
+
|
|
22
|
+
- The sign-in message's `domain` is the page's host
|
|
23
|
+
(`window.location.host`). A `file:` page has an empty host, and the
|
|
24
|
+
Keycloak wallet SPI refuses a message whose domain is not allowed.
|
|
25
|
+
- Add the page's host (with its port, if not 443) to the realm's
|
|
26
|
+
`siww.allowedDomains` (SHC Keycloak) or `wallet.allowedDomains` (mpo
|
|
27
|
+
Keycloak).
|
|
28
|
+
- Add the page's origin to the Keycloak client's **Web origins**. The page
|
|
29
|
+
calls Keycloak with `fetch` and credentials, so CORS must allow it.
|
|
30
|
+
- The nonce is bound to a `KEYCLOAK_SESSION_SIWW` / `KEYCLOAK_SESSION_WALLET`
|
|
31
|
+
cookie. When the page and Keycloak are on different sites that cookie has to
|
|
32
|
+
be `SameSite=None; Secure`, which Keycloak only sends over https.
|
|
33
|
+
- Plain http is accepted in development builds only, on `localhost`,
|
|
34
|
+
`127.0.0.1`, `[::1]` and `10.0.2.2` (the Android emulator's address for the
|
|
35
|
+
host machine). Reach a dev server on the host from an emulator with
|
|
36
|
+
`adb reverse tcp:8099 tcp:8099` and `http://localhost:8099/webview.html`. A
|
|
37
|
+
release build refuses them: on a phone any app can listen on a loopback
|
|
38
|
+
port, and `10.0.2.2` is an ordinary network address.
|
|
39
|
+
|
|
40
|
+
The page refuses `auth` requests with `-32001` when it is not hosted, and the
|
|
41
|
+
React Native host refuses to mount a WebView for such a URL.
|
|
42
|
+
|
|
43
|
+
## 2. Transport
|
|
44
|
+
|
|
45
|
+
All messages are JSON text, one message per string.
|
|
46
|
+
|
|
47
|
+
| direction | mechanism |
|
|
48
|
+
| ------------ | ------------------------------------------------------------------------------------------- |
|
|
49
|
+
| page to host | the page calls `window.ReactNativeWebView.postMessage(text)` |
|
|
50
|
+
| host to page | the host evaluates the delivery script below |
|
|
51
|
+
| host config | before the page's scripts run, the host sets `window.__web3Config = <object>` (section 2.1) |
|
|
52
|
+
|
|
53
|
+
The delivery script hands one message to the page only while the top frame
|
|
54
|
+
is still on the page's origin:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
window.location.origin === "<page origin>" &&
|
|
58
|
+
window.__bridgeReceive &&
|
|
59
|
+
window.__bridgeReceive(<text as JS string>);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`<text as JS string>` is the message text encoded as a JavaScript string
|
|
63
|
+
literal. A JSON encoder's string output is one (escape `U+2028` and `U+2029`
|
|
64
|
+
as well if your encoder does not).
|
|
65
|
+
|
|
66
|
+
Accept a page message only when it comes from the top frame on the page's
|
|
67
|
+
origin. Drop one whose sending frame or origin the WebView does not report:
|
|
68
|
+
a cross-origin frame inside the page (an ad, a wallet SDK's iframe) can call
|
|
69
|
+
the same function, and a forged `tokensChanged` would sign the user in as
|
|
70
|
+
someone else.
|
|
71
|
+
|
|
72
|
+
Write the page origin the way `location.origin` does: lowercase scheme and
|
|
73
|
+
host, punycode for an internationalized host, and the port only when it is
|
|
74
|
+
not the scheme's default (`WKSecurityOrigin.port` is 0 for the default).
|
|
75
|
+
|
|
76
|
+
The React Native host in this package is looser than this section asks:
|
|
77
|
+
react-native-webview reports the sending frame's URL but not whether it is
|
|
78
|
+
the top frame, so it accepts same-origin frames, and on an Android WebView
|
|
79
|
+
without `WEB_MESSAGE_LISTENER` it sees the top frame's URL for every frame.
|
|
80
|
+
The origin check in the delivery script still holds there.
|
|
81
|
+
|
|
82
|
+
**Android (Kotlin).** Receive page messages with
|
|
83
|
+
`WebViewCompat.addWebMessageListener(webView, "ReactNativeWebView", setOf(pageOrigin), listener)`,
|
|
84
|
+
which gives the page a `ReactNativeWebView.postMessage(text)`, and in the
|
|
85
|
+
listener accept a message only when `isMainFrame` is true and `sourceOrigin`
|
|
86
|
+
is the page's origin. Do not use `addJavascriptInterface`: it is exposed to
|
|
87
|
+
every frame and does not say which one called. On a WebView without
|
|
88
|
+
`WebViewFeature.WEB_MESSAGE_LISTENER`, do not run the bridge. Deliver host
|
|
89
|
+
messages with `webView.evaluateJavascript(...)` on the UI thread. Inject the
|
|
90
|
+
config with a document-start script
|
|
91
|
+
(`WebViewCompat.addDocumentStartJavaScript`, allowed origins `setOf(pageOrigin)`).
|
|
92
|
+
|
|
93
|
+
**iOS (Swift).** Register a `WKScriptMessageHandler` under the name
|
|
94
|
+
`ReactNativeWebView` and accept a message only when
|
|
95
|
+
`message.frameInfo.isMainFrame` is true and `message.frameInfo.securityOrigin`
|
|
96
|
+
is the page's (protocol, host and port). Add this user script at document
|
|
97
|
+
start, main frame only, so the page finds the function it calls:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
window.ReactNativeWebView = {
|
|
101
|
+
postMessage: (text) => window.webkit.messageHandlers.ReactNativeWebView.postMessage(text),
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Deliver host messages with `webView.evaluateJavaScript(...)`.
|
|
106
|
+
|
|
107
|
+
### 2.1 Config
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
window.__web3Config = {
|
|
111
|
+
appName: "QuickCam",
|
|
112
|
+
appDescription: "Connect your wallet",
|
|
113
|
+
appUrl: "https://quickcam.app",
|
|
114
|
+
appIcon: "https://quickcam.app/icon.png",
|
|
115
|
+
solanaRpcUrl: "https://api.mainnet-beta.solana.com",
|
|
116
|
+
mockWallet: false,
|
|
117
|
+
};
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Every field but `appName` is optional, and the page ignores fields it does
|
|
121
|
+
not know (the React Native host passes its whole `Web3Config`).
|
|
122
|
+
`mockWallet: true` replaces every
|
|
123
|
+
wallet with an in-page test signer that produces real signatures; it is for
|
|
124
|
+
end-to-end tests and must never be set in a release build.
|
|
125
|
+
|
|
126
|
+
## 3. Envelope
|
|
127
|
+
|
|
128
|
+
| field | type | present on | meaning |
|
|
129
|
+
| -------- | ------ | ---------------- | ------------------------------------------------------- |
|
|
130
|
+
| `id` | string | `req`, `res` | chosen by the requester, echoed by the response |
|
|
131
|
+
| `ns` | string | always | namespace: `evm`, `solana`, `sui`, `gpg`, `auth`, `sys` |
|
|
132
|
+
| `kind` | string | always | `req`, `res` or `event` |
|
|
133
|
+
| `method` | string | `req`, `event` | the operation or event name |
|
|
134
|
+
| `params` | any | `req`, `event` | method input, omitted when there is none |
|
|
135
|
+
| `result` | any | `res` on success | method output (`null` when there is nothing to return) |
|
|
136
|
+
| `error` | object | `res` on failure | `{ "code": number, "message": string, "data"?: any }` |
|
|
137
|
+
|
|
138
|
+
Rules:
|
|
139
|
+
|
|
140
|
+
- The host sends `req`; the page answers each one with exactly one `res` with
|
|
141
|
+
the same `id`, in whatever order they finish. The page sends `event`s at any
|
|
142
|
+
time; events carry no `id` and get no answer.
|
|
143
|
+
- `id` must be unique among the host's requests in flight. Any string works;
|
|
144
|
+
the React Native host uses a counter.
|
|
145
|
+
- Drop any text that is not JSON, and any message whose `ns` or `kind` is not
|
|
146
|
+
in the lists above. Ignore a `res` whose `id` you are not waiting for, and
|
|
147
|
+
events and fields you do not know.
|
|
148
|
+
- Bytes cross as standard base64 with padding, never as arrays.
|
|
149
|
+
- A request that waits on the user (a wallet signature, a GPG paste) can take
|
|
150
|
+
minutes. The React Native host times out sign-in after 10 minutes and GPG
|
|
151
|
+
after 15; plain requests after 2.
|
|
152
|
+
|
|
153
|
+
Request and response:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{ "id": "7", "ns": "evm", "kind": "req", "method": "eth_chainId" }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{ "id": "7", "ns": "evm", "kind": "res", "result": "0x2105" }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Error response:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"id": "8",
|
|
168
|
+
"ns": "evm",
|
|
169
|
+
"kind": "res",
|
|
170
|
+
"error": { "code": 4001, "message": "User rejected the request." }
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Event:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"ns": "evm",
|
|
179
|
+
"kind": "event",
|
|
180
|
+
"method": "accountsChanged",
|
|
181
|
+
"params": ["0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"]
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 4. Lifecycle
|
|
186
|
+
|
|
187
|
+
1. The host loads the page URL with the config injected.
|
|
188
|
+
2. The page registers its namespaces and sends `sys.ready`. Until then the
|
|
189
|
+
host queues its requests; it must not deliver any before `ready`.
|
|
190
|
+
3. The host reads `protocol` and `namespaces` from `ready`. A page whose
|
|
191
|
+
`protocol` is higher than the host supports may have changed a message the
|
|
192
|
+
host relies on: warn, and do not call methods the host does not know.
|
|
193
|
+
Before calling a namespace, check that it is listed; a page built without
|
|
194
|
+
it answers `-32601`.
|
|
195
|
+
4. On a reload the page sends `ready` again. Requests in flight when the page
|
|
196
|
+
went away never get an answer: fail them on the host (a reload, a crash,
|
|
197
|
+
`onRenderProcessGone` / `webViewWebContentProcessDidTerminate`).
|
|
198
|
+
5. When the app returns to the foreground (typically back from a wallet app)
|
|
199
|
+
the host sends `sys.resync` so the page re-reports account state.
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"ns": "sys",
|
|
204
|
+
"kind": "event",
|
|
205
|
+
"method": "ready",
|
|
206
|
+
"params": { "protocol": 1, "namespaces": ["evm", "solana", "sui", "gpg", "auth", "sys"] }
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Versioning: `protocol` changes only for a change an existing host could not
|
|
211
|
+
ignore (a renamed method, a changed result shape, a different transport). New
|
|
212
|
+
namespaces, methods, events, optional params and result fields are added
|
|
213
|
+
without a bump, which is why hosts ignore what they do not know.
|
|
214
|
+
|
|
215
|
+
## 5. Navigation and wallet hand-off
|
|
216
|
+
|
|
217
|
+
Wallets are separate apps. The page opens them by navigating to a wallet URL
|
|
218
|
+
or opening one in a new window; the host must hand those to the OS and must
|
|
219
|
+
keep the page itself in place.
|
|
220
|
+
|
|
221
|
+
Top-frame navigations (`shouldOverrideUrlLoading` /
|
|
222
|
+
`decidePolicyFor navigationAction`):
|
|
223
|
+
|
|
224
|
+
| URL | host does |
|
|
225
|
+
| --------------------------------------------------------------- | ------------------------ |
|
|
226
|
+
| a wallet scheme or wallet universal link (lists below) | open with the OS, cancel |
|
|
227
|
+
| same origin as the page, or `about:blank` | allow |
|
|
228
|
+
| any other `http`/`https` URL, `mailto:`, `tel:`, `sms:` | open with the OS, cancel |
|
|
229
|
+
| anything else (`javascript:`, `file:`, `data:`, `intent:`, ...) | cancel |
|
|
230
|
+
|
|
231
|
+
The top frame must never leave the page's origin: the page's messages carry
|
|
232
|
+
tokens, and a foreign page would receive them. Android does not ask
|
|
233
|
+
`shouldOverrideUrlLoading` about a POST (a form with `target=_top`), so also
|
|
234
|
+
watch the top frame start loading (`onPageStarted` /
|
|
235
|
+
`didStartProvisionalNavigation`): a document on another origin means the page
|
|
236
|
+
is gone. Fail what is in flight and deliver nothing until the next
|
|
237
|
+
`sys.ready`, then load the page's URL again (not a reload, which would reload
|
|
238
|
+
the foreign document), twice at most until the page announces itself. Sub-frame loads are the page's business; allow them
|
|
239
|
+
unless they are wallet links.
|
|
240
|
+
|
|
241
|
+
New windows (`window.open`, `target=_blank`; `onCreateWindow` /
|
|
242
|
+
`createWebViewWith`) never open in the app: wallet links and `http`/`https`
|
|
243
|
+
URLs go to the OS, everything else is dropped. Allow the page to open windows
|
|
244
|
+
without a user gesture (`javaScriptCanOpenWindowsAutomatically`): a wallet
|
|
245
|
+
link is often opened after an `await`.
|
|
246
|
+
|
|
247
|
+
Wallet schemes: `ethereum`, `metamask`, `rainbow`, `trust`, `phantom`,
|
|
248
|
+
`solflare`, `backpack`, `solana`, `cbwallet`, `ledgerlive`, `zerion`,
|
|
249
|
+
`rabby`, `okx`, `imtokenv2`, `wallet`.
|
|
250
|
+
|
|
251
|
+
Wallet universal-link hosts (and their subdomains): `metamask.app.link`,
|
|
252
|
+
`link.trustwallet.com`, `phantom.app`, `solflare.com`, `backpack.app`,
|
|
253
|
+
`rnbwapp.com`, `go.cb-w.com`, `ledger.com`.
|
|
254
|
+
|
|
255
|
+
A wallet that sends the user back opens the app's own deep link. The host may
|
|
256
|
+
forward the query parameters of its wallet-return link with
|
|
257
|
+
`sys.deepLinkReturn`, and only that link: never Keycloak's onboarding
|
|
258
|
+
redirect, whose `code` is the host's. MetaMask Connect needs only the
|
|
259
|
+
`resync`.
|
|
260
|
+
|
|
261
|
+
## 6. Errors
|
|
262
|
+
|
|
263
|
+
| code | meaning |
|
|
264
|
+
| -------- | ------------------------------------------------------------------------------------------------- |
|
|
265
|
+
| `4001` | the user rejected the request (in the wallet, or by cancelling the GPG paste) |
|
|
266
|
+
| `4200` | the wallet does not support the method |
|
|
267
|
+
| `-32601` | unknown namespace or method |
|
|
268
|
+
| `-32602` | invalid params |
|
|
269
|
+
| `-32000` | any other failure; `message` says what |
|
|
270
|
+
| `-32001` | the page is not hosted (section 1), so it cannot sign in |
|
|
271
|
+
| `-32002` | Keycloak refused; `data` is `{ "status": number, "error"?: string, "errorDescription"?: string }` |
|
|
272
|
+
| `-32003` | the page has no wallet or signer for the requested family |
|
|
273
|
+
| `-32004` | the account has required actions left and no `onboarding` client was given |
|
|
274
|
+
|
|
275
|
+
`evm` errors are whatever the wallet's EIP-1193 provider threw, with its code.
|
|
276
|
+
|
|
277
|
+
## 7. Namespaces
|
|
278
|
+
|
|
279
|
+
### `sys`
|
|
280
|
+
|
|
281
|
+
| method | direction | params | result |
|
|
282
|
+
| ---------------- | ------------------- | ----------------------------------------------- | ------ |
|
|
283
|
+
| `ready` | event, page to host | `{ protocol, namespaces }` | |
|
|
284
|
+
| `modalOpen` | event, page to host | none | |
|
|
285
|
+
| `modalClose` | event, page to host | none | |
|
|
286
|
+
| `resync` | req | none | `null` |
|
|
287
|
+
| `deepLinkReturn` | req | the return URL's query, as an object of strings | `null` |
|
|
288
|
+
|
|
289
|
+
Keep the WebView mounted for the app's whole life but invisible, and show it
|
|
290
|
+
full screen between `modalOpen` and `modalClose`: the page raises them around
|
|
291
|
+
the connect modal and the GPG paste box. A hidden WebView keeps its wallet
|
|
292
|
+
sessions; destroying it drops them.
|
|
293
|
+
|
|
294
|
+
### `evm`
|
|
295
|
+
|
|
296
|
+
Every request is an EIP-1193 call forwarded to the page's connected wallet:
|
|
297
|
+
`method` is the RPC method, `params` its params array, `result` its result.
|
|
298
|
+
`eth_requestAccounts` opens the connect modal when nothing is connected and
|
|
299
|
+
answers once a wallet connects. `personal_sign` takes the message as 0x hex.
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"id": "12",
|
|
304
|
+
"ns": "evm",
|
|
305
|
+
"kind": "req",
|
|
306
|
+
"method": "personal_sign",
|
|
307
|
+
"params": ["0x48656c6c6f", "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"]
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Events: `accountsChanged` (array of addresses), `chainChanged` (hex chain id),
|
|
312
|
+
`connect`, `disconnect`.
|
|
313
|
+
|
|
314
|
+
### `solana`
|
|
315
|
+
|
|
316
|
+
| method | params | result |
|
|
317
|
+
| --------------------- | ------------------------------ | --------------------------------------------- |
|
|
318
|
+
| `connect` | none | `{ "publicKey": base58 }` |
|
|
319
|
+
| `disconnect` | none | `null` |
|
|
320
|
+
| `signMessage` | `{ "message": base64 }` | `{ "signature": base64 }` (ed25519, 64 bytes) |
|
|
321
|
+
| `signTransaction` | `{ "transaction": base64 }` | `{ "transaction": base64 }` |
|
|
322
|
+
| `signAllTransactions` | `{ "transactions": [base64] }` | `{ "transactions": [base64] }` |
|
|
323
|
+
|
|
324
|
+
Transactions are serialized legacy or versioned transactions. Event:
|
|
325
|
+
`accountChanged` with `{ "publicKey": base58 | null }`.
|
|
326
|
+
|
|
327
|
+
### `sui`
|
|
328
|
+
|
|
329
|
+
| method | params | result |
|
|
330
|
+
| ------------- | ----------------------- | ------------------------- |
|
|
331
|
+
| `connect` | none | `{ "address": "0x…" }` |
|
|
332
|
+
| `disconnect` | none | `null` |
|
|
333
|
+
| `signMessage` | `{ "message": string }` | `{ "signature": base64 }` |
|
|
334
|
+
|
|
335
|
+
`message` is UTF-8 text, signed as a Sui personal message. `signature` is
|
|
336
|
+
Sui's serialized signature (flag, signature, public key), the form the
|
|
337
|
+
Keycloak Sui verifier takes. `signMessage` connects first when needed. Event:
|
|
338
|
+
`accountChanged` with `{ "address": string | null }`.
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"id": "20",
|
|
343
|
+
"ns": "sui",
|
|
344
|
+
"kind": "req",
|
|
345
|
+
"method": "signMessage",
|
|
346
|
+
"params": { "message": "Sign in With Sui." }
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### `gpg`
|
|
351
|
+
|
|
352
|
+
GPG signing is copy and paste: the user runs a command in a terminal and
|
|
353
|
+
pastes its output.
|
|
354
|
+
|
|
355
|
+
| method | params | result |
|
|
356
|
+
| ------------- | ------------------------- | --------------------------------------------------------------------- |
|
|
357
|
+
| `signMessage` | `{ "message": string }` | `{ "signature": string }`: armored signature, then armored public key |
|
|
358
|
+
| `submit` | `{ "signature": string }` | `null`; `-32602` if the paste is incomplete or covers another message |
|
|
359
|
+
| `cancel` | none | `null`; the pending `signMessage` fails with `4001` |
|
|
360
|
+
|
|
361
|
+
`signMessage` stays pending until pasted output settles it. By default the
|
|
362
|
+
page shows its own paste box (and raises `sys.modalOpen`). A host that draws
|
|
363
|
+
its own listens for `pendingChanged` and calls `submit`. A second
|
|
364
|
+
`signMessage` replaces the first, which fails.
|
|
365
|
+
|
|
366
|
+
Event `pendingChanged`: `{ "request": { "message": string, "command": string } | null }`.
|
|
367
|
+
|
|
368
|
+
```json
|
|
369
|
+
{
|
|
370
|
+
"ns": "gpg",
|
|
371
|
+
"kind": "event",
|
|
372
|
+
"method": "pendingChanged",
|
|
373
|
+
"params": {
|
|
374
|
+
"request": {
|
|
375
|
+
"message": "wallet.example.com wants you to sign in with your GPG key.",
|
|
376
|
+
"command": "{ printf %s '…' | gpg --detach-sign --armor; gpg --armor --export; }"
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### `auth`
|
|
383
|
+
|
|
384
|
+
Keycloak wallet sign-in, run inside the page so the nonce cookie and the
|
|
385
|
+
message domain belong to the hosted page. The host receives tokens.
|
|
386
|
+
|
|
387
|
+
Shared params:
|
|
388
|
+
|
|
389
|
+
- `keycloak`: `{ "baseUrl": string, "realm": string, "resource"?: "siww" | "wallet", "clientId": string, "scope"?: string | [string] }`.
|
|
390
|
+
`baseUrl` is Keycloak's root (`https://account.example.com`, or with `/auth`
|
|
391
|
+
on a Keycloak that still serves it there). `resource` is `siww` on the SHC
|
|
392
|
+
Keycloak (the default) and `wallet` on mpo's. `clientId` is a public client
|
|
393
|
+
with direct access grants enabled.
|
|
394
|
+
- `onboarding`: `{ "clientId": string, "redirectUri": string, "scope"?: string | [string] }`,
|
|
395
|
+
a client with the standard flow enabled and `redirectUri` (the app's deep
|
|
396
|
+
link) registered exactly.
|
|
397
|
+
|
|
398
|
+
Tokens: `{ "accessToken", "refreshToken"?, "idToken"?, "tokenType", "scope"?, "expiresAt", "refreshExpiresAt"? }`,
|
|
399
|
+
times in epoch milliseconds.
|
|
400
|
+
|
|
401
|
+
| method | params | result |
|
|
402
|
+
| --------- | ------------------------------------------ | ------------------------ |
|
|
403
|
+
| `signIn` | `{ "family"?, "keycloak", "onboarding"? }` | a sign-in result (below) |
|
|
404
|
+
| `refresh` | `{ "keycloak", "refreshToken"? }` | `{ "tokens": Tokens }` |
|
|
405
|
+
| `logout` | `{ "keycloak", "refreshToken"? }` | `null` |
|
|
406
|
+
|
|
407
|
+
`family` is `eth` (default), `sol`, `sui` or `gpg`. `signIn` connects that
|
|
408
|
+
family's wallet (opening the modal if needed), fetches a nonce from
|
|
409
|
+
`<baseUrl>/realms/<realm>/<resource>/nonce`, builds the family's sign-in
|
|
410
|
+
message with the page's host as domain, has the wallet sign it, and trades it
|
|
411
|
+
for tokens with a password grant (`username` = signature, `password` =
|
|
412
|
+
base64 of the message). `refresh` and `logout` default to the page's stored
|
|
413
|
+
refresh token for that realm and client; after a page reload, pass the one
|
|
414
|
+
the host kept. A `logout` Keycloak refuses fails with `-32002` (the page's
|
|
415
|
+
own session is cleared either way), so a host never takes a live token for
|
|
416
|
+
a revoked one. `400` with `invalid_grant` means Keycloak no longer honours
|
|
417
|
+
that refresh token, and the host can drop it.
|
|
418
|
+
|
|
419
|
+
Sign-in results:
|
|
420
|
+
|
|
421
|
+
- `{ "status": "signed-in", "family", "address", "tokens" }`. `address` is
|
|
422
|
+
null for GPG.
|
|
423
|
+
- `{ "status": "profile-incomplete", "family", "address", "browserLogin": { "url", "state", "codeVerifier" } }`.
|
|
424
|
+
Keycloak took the signature but the account has required actions (a new
|
|
425
|
+
user's profile form) that a direct grant cannot run. Check that `url` starts
|
|
426
|
+
with `<baseUrl>/realms/<realm>/protocol/openid-connect/auth?` for the
|
|
427
|
+
`keycloak` the host sent, then open it in the system browser once (never in
|
|
428
|
+
the WebView, never in a loop). Keycloak shows its own forms there and then
|
|
429
|
+
redirects to `redirectUri` with `code` and `state`. When `state` matches,
|
|
430
|
+
call `signIn` again, which now succeeds; a return carrying `error` (the user
|
|
431
|
+
cancelled) ends the onboarding instead. A host may also redeem `code` with
|
|
432
|
+
`codeVerifier` (PKCE S256) at the token endpoint for tokens of the
|
|
433
|
+
onboarding client.
|
|
434
|
+
|
|
435
|
+
Event `tokensChanged`: `{ "baseUrl", "realm", "clientId", "tokens": Tokens | null }`
|
|
436
|
+
on every sign-in, refresh and logout. Persist the refresh token from it.
|
|
437
|
+
|
|
438
|
+
```json
|
|
439
|
+
{
|
|
440
|
+
"id": "30",
|
|
441
|
+
"ns": "auth",
|
|
442
|
+
"kind": "req",
|
|
443
|
+
"method": "signIn",
|
|
444
|
+
"params": {
|
|
445
|
+
"family": "eth",
|
|
446
|
+
"keycloak": {
|
|
447
|
+
"baseUrl": "https://account.example.com",
|
|
448
|
+
"realm": "main",
|
|
449
|
+
"resource": "wallet",
|
|
450
|
+
"clientId": "siwe-public"
|
|
451
|
+
},
|
|
452
|
+
"onboarding": { "clientId": "wallet-onboarding", "redirectUri": "quickcam://auth" }
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
```json
|
|
458
|
+
{
|
|
459
|
+
"id": "30",
|
|
460
|
+
"ns": "auth",
|
|
461
|
+
"kind": "res",
|
|
462
|
+
"result": {
|
|
463
|
+
"status": "profile-incomplete",
|
|
464
|
+
"family": "eth",
|
|
465
|
+
"address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
|
|
466
|
+
"browserLogin": {
|
|
467
|
+
"url": "https://account.example.com/realms/main/protocol/openid-connect/auth?client_id=wallet-onboarding&redirect_uri=quickcam%3A%2F%2Fauth&response_type=code&scope=openid&state=Q2x1&code_challenge=E9Mel&code_challenge_method=S256",
|
|
468
|
+
"state": "Q2x1",
|
|
469
|
+
"codeVerifier": "dBjftJeZ4CVP"
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## 8. Security
|
|
476
|
+
|
|
477
|
+
- Keys never cross the bridge. Only addresses, signatures and tokens do, and
|
|
478
|
+
every signature needs the wallet's own approval.
|
|
479
|
+
- Load only the page you host, keep its top frame on its origin (section 5),
|
|
480
|
+
accept page messages only from its top frame on its origin, and deliver
|
|
481
|
+
messages only while the top frame is on that origin (section 2).
|
|
482
|
+
- Tokens arrive in `auth` results and `tokensChanged`. Store them the way the
|
|
483
|
+
app stores any credential (Keystore, Keychain); never log them.
|
|
484
|
+
- `mockWallet` signs with a throwaway in-page key and approves everything.
|
|
485
|
+
It exists for tests.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/web3",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.25.0",
|
|
4
4
|
"description": "Web3 wallet integration for multiplatform.one ecosystem with ConnectKit and wagmi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"connectkit",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"source": "src/index.ts",
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
|
+
"docs",
|
|
26
27
|
"src",
|
|
27
28
|
"types",
|
|
28
29
|
"!types/.tsbuildinfo"
|
|
@@ -53,6 +54,13 @@
|
|
|
53
54
|
"require": "./dist/cjs/index.native.js",
|
|
54
55
|
"default": "./dist/esm/index.native.js"
|
|
55
56
|
},
|
|
57
|
+
"./bridge": {
|
|
58
|
+
"source": "./src/bridge/core.ts",
|
|
59
|
+
"react-native": "./src/bridge/core.ts",
|
|
60
|
+
"types": "./types/bridge/core.d.ts",
|
|
61
|
+
"import": "./dist/esm/bridge/core.mjs",
|
|
62
|
+
"require": "./dist/cjs/bridge/core.cjs"
|
|
63
|
+
},
|
|
56
64
|
"./connectkit": {
|
|
57
65
|
"source": "./src/connectkit/index.ts",
|
|
58
66
|
"types": "./types/connectkit/index.d.ts",
|
|
@@ -99,10 +107,10 @@
|
|
|
99
107
|
"dependencies": {
|
|
100
108
|
"@aave/account": "^0.2.0",
|
|
101
109
|
"@metamask/connect-evm": "^2.1.1",
|
|
102
|
-
"@multiplatform.one/connectkit": "7.
|
|
103
|
-
"@multiplatform.one/gpg": "7.
|
|
104
|
-
"@multiplatform.one/platform": "7.
|
|
105
|
-
"@multiplatform.one/theme": "7.
|
|
110
|
+
"@multiplatform.one/connectkit": "7.25.0",
|
|
111
|
+
"@multiplatform.one/gpg": "7.25.0",
|
|
112
|
+
"@multiplatform.one/platform": "7.25.0",
|
|
113
|
+
"@multiplatform.one/theme": "7.25.0",
|
|
106
114
|
"@noble/curves": "^1.9.7",
|
|
107
115
|
"@solana/kit": "^8.3.0",
|
|
108
116
|
"@solana/wallet-adapter-base": "^0.9.27",
|
|
@@ -126,7 +134,7 @@
|
|
|
126
134
|
"wagmi": "^3.7.1"
|
|
127
135
|
},
|
|
128
136
|
"devDependencies": {
|
|
129
|
-
"@multiplatform.one/config": "7.
|
|
137
|
+
"@multiplatform.one/config": "7.25.0",
|
|
130
138
|
"@tamagui/build": "2.7.6",
|
|
131
139
|
"@tanstack/react-query": "^5.100.7",
|
|
132
140
|
"@testing-library/jest-dom": "^6.9.1",
|