@cantor8/wallet-connect-sdk 0.3.0-alpha.1
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 +90 -0
- package/dist/discovery.d.ts +8 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.esm.js +1 -0
- package/dist/provider.d.ts +40 -0
- package/dist/session.d.ts +33 -0
- package/dist/transport.d.ts +6 -0
- package/dist/transports/IFrameTransport.d.ts +46 -0
- package/dist/transports/ThinTransport.d.ts +36 -0
- package/dist/transports/Transport.d.ts +7 -0
- package/dist/transports/WebViewTransport.d.ts +39 -0
- package/dist/transports/WindowTransport.d.ts +46 -0
- package/dist/transports/constants.d.ts +7 -0
- package/dist/types.d.ts +212 -0
- package/dist/utils/HttpClient.d.ts +8 -0
- package/dist/utils/HttpClient.types.d.ts +31 -0
- package/dist/utils/PollingManager.d.ts +27 -0
- package/dist/utils/instruments.d.ts +2 -0
- package/dist/utils/storage.d.ts +19 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
# C8 Wallet Connect SDK
|
|
3
|
+
|
|
4
|
+
Lightweight SDK for dApp developers to integrate the C8 Wallet via a popup window and postMessage communication.
|
|
5
|
+
|
|
6
|
+
Quick start
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
You can configure the provider construction:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
const c8 = new C8WalletProvider({
|
|
15
|
+
dappUrl: window.location.href,
|
|
16
|
+
dappName: "Cantor8 Wallet Connect SDK Demo",
|
|
17
|
+
network: "devnet"
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Sign up for events:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
c8.on('connected', (e) => console.log('Connected', e));
|
|
25
|
+
c8.on('disconnected', (e) => console.log('Disconnected', e));
|
|
26
|
+
c8.on('accountChanged', (e) => console.log('account's balance changed', e));
|
|
27
|
+
c8.on('txInitiated', (e) => console.log('TX initiated', e));
|
|
28
|
+
c8.on('txChanged', (e) => console.log('TX changed', e));
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Basic usage
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
const c8 = new C8WalletProvider({
|
|
35
|
+
dappUrl: window.location.href,
|
|
36
|
+
dappName: "Cantor8 Wallet Connect SDK Demo",
|
|
37
|
+
network: "devnet"
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await c8.connect();
|
|
41
|
+
|
|
42
|
+
// Instruments list type: InstrumentListPayload
|
|
43
|
+
const instruments = await c8.getInstruments();
|
|
44
|
+
console.log('Instruments', instruments);
|
|
45
|
+
|
|
46
|
+
const firstInstrumentId = instruments.instruments[0]?.instrumentId;
|
|
47
|
+
|
|
48
|
+
// Accounts list type: AccountListPayload
|
|
49
|
+
const accounts = await wallet.getAccounts(firstInstrumentId);
|
|
50
|
+
console.log('Accounts', accounts);
|
|
51
|
+
|
|
52
|
+
const senderPartyId = accounts.accounts[0]?.partyId;
|
|
53
|
+
const senderHoldingInstrumentId = accounts.accounts[0]?.holdings[0]?.instrumentId || firstInstrumentId;
|
|
54
|
+
|
|
55
|
+
// Submit a transfer
|
|
56
|
+
// SubmitTransferResultPayload
|
|
57
|
+
const res = await c8.send({
|
|
58
|
+
senderPartyId,
|
|
59
|
+
instrumentId: senderHoldingInstrumentId,
|
|
60
|
+
amount: 1.23,
|
|
61
|
+
receiverPartyId: 'Party::Receiver',
|
|
62
|
+
});
|
|
63
|
+
console.log('Send result', res); // { txId }
|
|
64
|
+
```
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
#### Public API (Provider)
|
|
68
|
+
|
|
69
|
+
| |
|
|
70
|
+
| :-------- |
|
|
71
|
+
| `connect(): Promise<void>` |
|
|
72
|
+
| `disconnect(): Promise<void>` |
|
|
73
|
+
| `status(): Promise<{connected: boolean, walletVersion?: string}>` |
|
|
74
|
+
| `getInstruments(): Promise<InstrumentListPayload>` |
|
|
75
|
+
| `getAccounts(instrumentId?: string): Promise<AccountListPayload>` |
|
|
76
|
+
| `send(input: {senderPartyId: string, instrumentId: string, amount: number, receiverPartyId: string, memo?: string, metadata?: Record<string, string>}): Promise<SubmitTransferResultPayload>` |
|
|
77
|
+
| `checkTxStatusById(input: {partyId: string, txId: string}): Promise<TransferStatusResponsePayload>` |
|
|
78
|
+
|
|
79
|
+
#### Events
|
|
80
|
+
|
|
81
|
+
| |
|
|
82
|
+
| :-------- |
|
|
83
|
+
| `connected` |
|
|
84
|
+
| `disconnected` |
|
|
85
|
+
| `accountChanged` |
|
|
86
|
+
| `txInitiated` |
|
|
87
|
+
| `txChanged` |
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type C8ProviderInfo = {
|
|
2
|
+
uuid: string;
|
|
3
|
+
name: "C8 Wallet";
|
|
4
|
+
icon: string;
|
|
5
|
+
rdns: "tech.cantor8.wallet";
|
|
6
|
+
};
|
|
7
|
+
export declare function announceC8Provider(get: () => any): void;
|
|
8
|
+
export declare function onC8ProviderDiscovered(cb: (info: C8ProviderInfo, provider: any) => void): () => void;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const e="https://wallet.dev.digik.cantor8.tech",t="https://wallet-backend.dev.digik.cantor8.tech";class s{static getItem(e){try{const t=localStorage.getItem(e);return t?JSON.parse(t):null}catch(e){return null}}static setItem(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(e){}}static removeItem(e){try{localStorage.removeItem(e)}catch(e){}}}const n={TestCoin1:"TestCoin1",Amulet:"Canton Coin",CBTC:"CBTC",USDCx:"USDCx",CETH:"CETH"},i=e=>{var t;return"Amulet"===e?"Canton Coin":null!=(t=n[null!=e?e:""])?t:e},r={TestCoin1:"TestCoin1",Amulet:"CC",CBTC:"CBTC",USDCx:"USDCx"},a=e=>{var t;return"Amulet"===e?"CC":null!=(t=r[null!=e?e:""])?t:e};var o=Object.defineProperty,h=(e,t,s)=>((e,t,s)=>t in e?o(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);const d=class e{constructor(){h(this,"appName"),h(this,"accounts",[]),h(this,"instruments",[]),h(this,"partyIds",[]),h(this,"authToken",null),h(this,"isConnected",!1),h(this,"expireAt",null),h(this,"disconnectTimeoutId",null),this.load()}static getInstance(){return e.instance||(e.instance=new e),e.instance}setAppName(e){this.appName=e}getAppName(){return this.appName}setInstruments(e){this.instruments=e}getInstruments(){return this.instruments}setAccounts(e){this.accounts=e,this.partyIds=e.map(e=>e.partyId),this.instruments=e.flatMap(e=>e.holdings.map(e=>({instrumentId:e.instrumentId,name:i(e.instrumentId),symbol:a(e.instrumentId)})))}getAccounts(){return this.accounts}setBearerToken(e,t){this.authToken=e,this.isConnected=!0,this.expireAt=t}getExpireAt(){return this.expireAt}setDisconnectTimeoutId(e){this.disconnectTimeoutId&&clearTimeout(this.disconnectTimeoutId),this.disconnectTimeoutId=e}getDisconnectTimeoutId(){return this.disconnectTimeoutId}getBearerToken(){return this.authToken}clear(){this.accounts=[],this.instruments=[],this.authToken=null,this.partyIds=[],this.isConnected=!1,this.expireAt=null,this.disconnectTimeoutId&&(clearTimeout(this.disconnectTimeoutId),this.disconnectTimeoutId=null),s.removeItem(e.SESSION_KEY)}save(){s.setItem(e.SESSION_KEY,{authToken:this.authToken,partyIds:this.partyIds,expireAt:this.expireAt})}setConnected(e){this.isConnected=e}getConnected(){return this.isConnected}hasStoredSession(){return!!s.getItem(e.SESSION_KEY)}load(){const t=s.getItem(e.SESSION_KEY);t&&(this.authToken=t.authToken,this.partyIds=t.partyIds||[],this.expireAt=t.expireAt||null)}};h(d,"instance"),h(d,"SESSION_KEY","c8-session");let c=d;var l=Object.defineProperty,u=(e,t,s)=>((e,t,s)=>t in e?l(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);const p=class e{constructor(e=5e3){this.pollingInterval=e,u(this,"events",new Map),u(this,"intervals",new Map),u(this,"handlerRegistry",new Map),this.restore()}static getInstance(t=5e3){return e.instance||(e.instance=new e(t)),e.instance}registerHandler(e,t){this.handlerRegistry.set(e,t),this.events.forEach((s,n)=>{s.event.type===e&&(this.stopPolling(n),s.handler=t,this.startPolling(n))})}add(e,t){const s=btoa(`${e}-${JSON.stringify(t)}`);this.events.has(s)&&this.remove(s);const n=this.handlerRegistry.get(e);if(!n)return;const i={key:s,type:e,params:t,createdAt:Date.now()};this.events.set(s,{event:i,handler:n}),this.persist(),this.startPolling(s)}remove(e){this.stopPolling(e),this.events.delete(e),this.persist()}startPolling(t){const s=this.events.get(t);if(!s)return;const{event:n,handler:i}=s,r=async()=>{try{if(n.createdAt&&Date.now()-n.createdAt>e.POLLING_TIMEOUT)return void this.remove(t);await i(n.params)&&this.remove(t)}catch(e){}};r();const a=window.setInterval(r,this.pollingInterval);this.intervals.set(t,a)}stopPolling(e){const t=this.intervals.get(e);void 0!==t&&(window.clearInterval(t),this.intervals.delete(e))}persist(){const t=Array.from(this.events.values()).map(e=>e.event);s.setItem(e.STORAGE_KEY,t)}restore(){const t=s.getItem(e.STORAGE_KEY);if(t&&Array.isArray(t)){const s=Date.now();t.forEach(t=>{if(t.createdAt&&s-t.createdAt>e.POLLING_TIMEOUT)return;const n=this.handlerRegistry.get(t.key);n?(this.events.set(t.key,{event:t,handler:n}),this.startPolling(t.key)):this.events.set(t.key,{event:t,handler:async()=>!1})})}}clear(){this.events.clear(),this.intervals.forEach(e=>window.clearInterval(e)),this.intervals.clear(),this.persist(),s.removeItem(e.STORAGE_KEY)}getEvents(){return Array.from(this.events.values()).map(e=>e.event)}};u(p,"EVENT_TYPES",{RESTORE_SESSION:"RESTORE_SESSION",TRACK_TX_STATUS:"TRACK_TX_STATUS",UPDATE_ACCOUNT:"UPDATE_ACCOUNT"}),u(p,"type"),u(p,"instance"),u(p,"STORAGE_KEY","c8-polling-events"),u(p,"POLLING_TIMEOUT",3e5);let m=p;var g=Object.defineProperty;class v{constructor(e){((e,t,s)=>{((e,t,s)=>{t in e?g(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s})(e,t+"",s)})(this,"baseUrl"),this.baseUrl=e.endsWith("/")?e.slice(0,-1):e}async request(e,t={}){const s=c.getInstance().getBearerToken(),n=c.getInstance().getAppName(),i=new Headers(t.headers);s&&(i.set("Authorization",`Bearer ${s}`),i.set("X-App-Name",null!=n?n:"Unknown App")),i.set("x-feat-decimals","1");const r=await fetch(`${this.baseUrl}${e}`,{...t,headers:i});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);return await r.json()}async getBalance(){return this.request("/api/balance")}async getTransferStatus(e){return this.request(`/api/transfer/status?command_id=${e}`)}}var T=Object.defineProperty,I=(e,t,s)=>((e,t,s)=>t in e?T(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);function f(){let e,t;return{promise:new Promise((s,n)=>{e=s,t=n}),resolve:e,reject:t}}class w{constructor(s,n,i=e){let r;switch(this.appName=s,this.appUrl=n,this.origin=i,I(this,"WINDOW_NAME","c8-wallet"),I(this,"WINDOW_WIDTH",475),I(this,"WINDOW_HEIGHT",762),I(this,"popup"),I(this,"sessionId",crypto.randomUUID()),I(this,"listening",!1),I(this,"walletReady",!1),I(this,"pending",new Map),I(this,"eventHandlers",new Set),I(this,"handshakeTimer"),I(this,"handshakeDeadline"),I(this,"closeWatcherTimer"),I(this,"pollingManager",m.getInstance()),I(this,"session",c.getInstance()),I(this,"initDeferred"),I(this,"httpClient"),this.onWindowMessage=this.onWindowMessage.bind(this),this.handleRestoreSession=this.handleRestoreSession.bind(this),this.handleTrackTxStatus=this.handleTrackTxStatus.bind(this),this.handleAccountUpdate=this.handleAccountUpdate.bind(this),this.session.setAppName(this.appName),this.attachListener(),this.origin){case e:r=t;break;case"https://wallet.cantor8.tech":case"https://wallet.main.digik.cantor8.tech":r="https://wallet-backend.main.cantor8.tech";break;default:r=t}this.httpClient=new v(r),this.pollingManager.registerHandler(m.EVENT_TYPES.RESTORE_SESSION,this.handleRestoreSession),this.pollingManager.registerHandler(m.EVENT_TYPES.TRACK_TX_STATUS,this.handleTrackTxStatus),this.pollingManager.registerHandler(m.EVENT_TYPES.UPDATE_ACCOUNT,this.handleAccountUpdate),this.checkRestoreSession()}checkRestoreSession(){this.session.hasStoredSession()&&this.pollingManager.add(m.EVENT_TYPES.RESTORE_SESSION,{sessionId:this.sessionId})}async handleAccountUpdate(e){try{const e=await this.httpClient.getBalance();if(e&&e.holdings){const t=[{partyId:e.party_id,holdings:Object.entries(e.holdings).map(([e,t])=>({instrumentId:e,balance:Number(t.balance),balanceUsd:Number(t.balance_usd)}))}];this.session.setAccounts(t),this.session.save()}return!0}catch(e){e instanceof Error&&e.message.includes("401")&&this.destroy()}return!1}async getTransferStatusById(e){try{const t=await this.httpClient.getTransferStatus(e);let s;switch(t.status){case"success":s="confirmed";break;case"failed":s="failed";break;default:s="pending"}return t.status=s,t}catch(e){return e instanceof Error&&e.message.includes("401")&&this.destroy(),null}}async handleTrackTxStatus(e){try{const t=await this.httpClient.getTransferStatus(e.txId);if(e.status!==t.status){let s;switch(t.status){case"success":s="confirmed";break;case"failed":s="failed";break;default:s="pending"}return this.emitSyntheticEvent({type:"txChanged",txId:e.txId,status:s}),e.status=t.status,this.pollingManager.persist(),"pending"!==t.status&&this.pollingManager.add(m.EVENT_TYPES.UPDATE_ACCOUNT,{txId:e.txId}),"success"===t.status||"failed"===t.status}}catch(t){if(t instanceof Error&&(t.message.includes("401")&&this.destroy(),t.message.includes("404")))return this.emitSyntheticEvent({type:"txChanged",txId:e.txId,status:"failed"}),!0}return!1}async handleRestoreSession(e){try{const e=await this.httpClient.getBalance();if(e&&e.holdings){const t=[{partyId:e.party_id,holdings:Object.entries(e.holdings).map(([e,t])=>({instrumentId:e,balance:Number(t.balance),balanceUsd:Number(t.balance_usd)}))}];this.session.setAccounts(t),this.session.save(),this.session.setConnected(!0),this.emitSyntheticEvent({type:"connected"});const s=this.session.getExpireAt();return s&&this.scheduleDisconnect(s),!0}}catch(e){e instanceof Error&&e.message.includes("401")&&this.destroy()}return!1}get WALLET_EMBEDDED(){return`${this.origin}/embedded/`}async init(e){var t;if(void 0!==this.popup&&(null==(t=this.popup)||!t.closed))return;if(this.initDeferred||(this.initDeferred=f()),this.listening||this.attachListener(),this.popup&&!this.popup.closed)return this.popup.focus(),null==this.handshakeTimer&&this.startHandshakeLoop(),this.initDeferred.promise;const s=new URL(null!=e?e:"",this.WALLET_EMBEDDED);if(this.popup=window.open(s,this.WINDOW_NAME,`width=${this.WINDOW_WIDTH},height=${this.WINDOW_HEIGHT}`),!this.popup){const e=new Error("Failed to open popup window");Object.assign(e,{code:"POPUP_BLOCKED",message:"browser blocked the popup window"}),this.rejectInit(e)}return this.startHandshakeLoop(),this.initDeferred.promise}emitSyntheticEvent(e){for(const t of this.eventHandlers)try{t({kind:"event",event:e})}catch(e){}}scheduleDisconnect(e){if(!e)return;const t=e-Date.now();if(t>0){const e=setTimeout(()=>{this.destroy("authToken expired")},t);this.session.setDisconnectTimeoutId(e)}else this.destroy("authToken expired")}destroy(e="destroyed"){try{this.emitSyntheticEvent({type:"disconnected",reason:e}),this.detachListener(),this.clearHandshakeLoop(),this.initDeferred&&(this.initDeferred.reject(new Error("Transport destroyed")),this.initDeferred=void 0);for(const[,e]of this.pending)e.reject(new Error("Transport destroyed"));this.pending.clear(),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=void 0,this.walletReady=!1,this.session.clear(),this.pollingManager.clear()}catch(e){}}async request(e,t,s){var n,i,r,a,o,h,d,c,l,u,p,m,g,v,T,I;const w=crypto.randomUUID(),E=f();this.pending.set(w,E);try{if("connect"===e){if(this.session.getBearerToken())return this.handleResponse({kind:"response",id:w,result:null}),E.promise;this.session.getBearerToken()||(this.walletReady=!1),await this.init()}if("send"===e&&(this.walletReady=!1,await this.init("confirmTransaction")),"signAndExecute"===e&&(this.walletReady=!1,await this.init("signAndExecute")),"status"===e)return this.handleResponse({kind:"response",id:w,result:{connected:this.session.getConnected(),walletVersion:void 0}}),E.promise;if(s&&(null==(n=this.popup)||n.focus()),"getInstruments"===e){const e=this.session.getInstruments();return this.handleResponse({kind:"response",id:w,result:{instruments:e}}),E.promise}if("getAccounts"===e){await this.handleAccountUpdate();const e=this.session.getAccounts();return this.handleResponse({kind:"response",id:w,result:{accounts:e}}),E.promise}if("checkTxStatusById"===e){const e=t,s=await this.getTransferStatusById(null==e?void 0:e.txId);if(s){const e={status:s.status,transfer:{senderPartyId:null!=(r=null==(i=s.transfer)?void 0:i.party_id)?r:"",receiverPartyId:null!=(o=null==(a=s.transfer)?void 0:a.party_id2)?o:"",amount:Number(null!=(d=null==(h=s.transfer)?void 0:h.amount)?d:"0"),networkFees:Number(null!=(l=null==(c=s.transfer)?void 0:c.network_fees)?l:"0"),instrumentId:null!=(p=null==(u=s.transfer)?void 0:u.instrument_id)?p:"",txId:null!=(g=null==(m=s.transfer)?void 0:m.command_id)?g:"",created_at:null!=(T=null==(v=s.transfer)?void 0:v.created_at)?T:"",memo:null==(I=s.transfer)?void 0:I.reason}};this.handleResponse({kind:"response",id:w,result:e})}else this.handleResponse({kind:"response",id:w,error:{code:"FAILED_TO_FETCH_TRANSFER_STATUS",message:"Failed to fetch transfer status"}});return E.promise}if("disconnect"===e)return this.handleResponse({kind:"response",id:w,result:null}),E.promise;const f={kind:"request",id:w,method:e,params:t,sessionId:this.sessionId};this.post(f)}catch(e){this.pending.delete(w),E.reject(e)}return E.promise}onEvent(e){return this.eventHandlers.add(e),()=>{this.eventHandlers.delete(e)}}attachListener(){this.listening||(window.addEventListener("message",this.onWindowMessage),this.listening=!0)}detachListener(){this.listening&&(window.removeEventListener("message",this.onWindowMessage),this.listening=!1)}post(e){try{if(!this.popup||this.popup.closed)return;this.popup.postMessage(e,this.origin)}catch(e){}}onWindowMessage(e){if(e.origin!==this.origin)return;const t=e.data;if(t&&"object"==typeof t){if("event"===t.kind){for(const e of this.eventHandlers)"txInitiated"===t.event.type&&this.pollingManager.add(m.EVENT_TYPES.TRACK_TX_STATUS,{txId:t.event.txId,status:"initiated"}),e(t);return}if("internal_event"===t.kind)return void this.pollingManager.add(t.event.type,{wop:"wopwop"});if("auth-flow"===t.kind&&(this.session.setBearerToken(t.token,t.expireAt),this.session.setAccounts(t.accounts),this.session.setInstruments(t.instruments),this.session.save(),this.scheduleDisconnect(t.expireAt)),"handshake-ack"===t.kind&&t.ok)return void this.handleHandshakeAck();"response"===t.kind&&this.handleResponse(t)}}handleHandshakeAck(){this.walletReady=!0,this.clearHandshakeLoop(),this.initDeferred&&(this.initDeferred.resolve(),this.initDeferred=void 0)}handleResponse(e){const t=this.pending.get(e.id);if(t)if(this.pending.delete(e.id),e.error){const s=new Error(e.error.message||"Unknown Error");Object.assign(s,{code:e.error.code,data:e.error.data}),t.reject(s)}else t.resolve(e.result)}startHandshakeLoop(){this.handshakeDeadline=Date.now()+55e3;const e=()=>{if(!this.walletReady)return!this.popup||this.popup.closed?(this.clearHandshakeLoop(),void this.rejectInit(new Error("Popup closed before handshake"))):this.handshakeDeadline&&Date.now()>this.handshakeDeadline?(this.clearHandshakeLoop(),void this.rejectInit(new Error("Handshake timed out"))):void this.post({kind:"handshake",sdkVersion:"0.0.0",sessionId:this.sessionId,dapp:{name:this.appName,url:this.appUrl}});this.clearHandshakeLoop()};e(),this.handshakeTimer=window.setInterval(e,300)}clearHandshakeLoop(){null!=this.handshakeTimer&&(clearInterval(this.handshakeTimer),this.handshakeTimer=void 0),this.handshakeDeadline=void 0}rejectInit(e){this.initDeferred&&(Object.assign(e,{code:"INITIALIZATION_FAILED",message:e.message}),this.initDeferred.reject(e),this.initDeferred=void 0)}startPopupClosedWatcher(){const e=this.popup;if(!e)return;const t=window.setInterval(()=>{(!e||e.closed)&&(clearInterval(t),this.destroy())},300);this.closeWatcherTimer=t}}var E=Object.defineProperty,y=(e,t,s)=>((e,t,s)=>t in e?E(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);const k={uuid:"c8-wallet-connect",name:"C8 Wallet",icon:"",rdns:"tech.cantor8.wallet"},S="c8#provider_discovery";exports.C8WalletProvider=class{constructor(t){var s,n,i;y(this,"transport"),y(this,"listeners",{});const r=null!=(s=t.dappName)?s:document.title||"Unknown dApp",a=null!=(n=t.dappUrl)?n:location.origin,o=null!=(i=t.network)?i:"mainnet";let h;if("devnet"!==o)throw new Error("Only devnet network is supported right now");if("devnet"!==o)throw new Error("Unsupported network: "+o);h=e,this.transport=new w(r,a,h),this.transport.onEvent(e=>{"event"===e.kind&&this.emit(e.event.type,e.event)})}async connect(){await this.transport.request("connect",void 0,!0)}async disconnect(){try{await this.transport.request("disconnect"),this.transport.destroy()}catch(e){}}status(){return this.transport.request("status")}getInstruments(){return this.transport.request("getInstruments")}getAccounts(e){return this.transport.request("getAccounts",{instrumentId:e})}send(e){return this.transport.request("send",e,!0)}signAndExecute(e){return this.transport.request("signAndExecute",e,!0)}signAndExecutePreparedTransfer(e){return this.transport.request("signAndExecutePreparedTransfer",e,!0)}acknowledge(e){return this.transport.request("acknowledge",e,!0)}checkTxStatusById(e){return this.transport.request("checkTxStatusById",e)}on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),()=>this.listeners[e].delete(t)}emit(e,t){var s;for(const n of null!=(s=this.listeners[e])?s:[])n(t)}},exports.HttpClient=v,exports.LocalStorageHelper=s,exports.announceC8Provider=function(e){const t={info:k,provider:e()};window.dispatchEvent(new CustomEvent(S,{detail:t}))},exports.onC8ProviderDiscovered=function(e){const t=t=>{const s=t;s.detail&&e(s.detail.info,s.detail.provider)};return window.addEventListener(S,t),()=>window.removeEventListener(S,t)};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e="https://wallet.dev.digik.cantor8.tech",t="https://wallet-backend.dev.digik.cantor8.tech";class s{static getItem(e){try{const t=localStorage.getItem(e);return t?JSON.parse(t):null}catch(e){return null}}static setItem(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(e){}}static removeItem(e){try{localStorage.removeItem(e)}catch(e){}}}const n={TestCoin1:"TestCoin1",Amulet:"Canton Coin",CBTC:"CBTC",USDCx:"USDCx",CETH:"CETH"},i=e=>{var t;return"Amulet"===e?"Canton Coin":null!=(t=n[null!=e?e:""])?t:e},r={TestCoin1:"TestCoin1",Amulet:"CC",CBTC:"CBTC",USDCx:"USDCx"},a=e=>{var t;return"Amulet"===e?"CC":null!=(t=r[null!=e?e:""])?t:e};var o=Object.defineProperty,h=(e,t,s)=>((e,t,s)=>t in e?o(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);const d=class e{constructor(){h(this,"appName"),h(this,"accounts",[]),h(this,"instruments",[]),h(this,"partyIds",[]),h(this,"authToken",null),h(this,"isConnected",!1),h(this,"expireAt",null),h(this,"disconnectTimeoutId",null),this.load()}static getInstance(){return e.instance||(e.instance=new e),e.instance}setAppName(e){this.appName=e}getAppName(){return this.appName}setInstruments(e){this.instruments=e}getInstruments(){return this.instruments}setAccounts(e){this.accounts=e,this.partyIds=e.map(e=>e.partyId),this.instruments=e.flatMap(e=>e.holdings.map(e=>({instrumentId:e.instrumentId,name:i(e.instrumentId),symbol:a(e.instrumentId)})))}getAccounts(){return this.accounts}setBearerToken(e,t){this.authToken=e,this.isConnected=!0,this.expireAt=t}getExpireAt(){return this.expireAt}setDisconnectTimeoutId(e){this.disconnectTimeoutId&&clearTimeout(this.disconnectTimeoutId),this.disconnectTimeoutId=e}getDisconnectTimeoutId(){return this.disconnectTimeoutId}getBearerToken(){return this.authToken}clear(){this.accounts=[],this.instruments=[],this.authToken=null,this.partyIds=[],this.isConnected=!1,this.expireAt=null,this.disconnectTimeoutId&&(clearTimeout(this.disconnectTimeoutId),this.disconnectTimeoutId=null),s.removeItem(e.SESSION_KEY)}save(){s.setItem(e.SESSION_KEY,{authToken:this.authToken,partyIds:this.partyIds,expireAt:this.expireAt})}setConnected(e){this.isConnected=e}getConnected(){return this.isConnected}hasStoredSession(){return!!s.getItem(e.SESSION_KEY)}load(){const t=s.getItem(e.SESSION_KEY);t&&(this.authToken=t.authToken,this.partyIds=t.partyIds||[],this.expireAt=t.expireAt||null)}};h(d,"instance"),h(d,"SESSION_KEY","c8-session");let c=d;var l=Object.defineProperty,u=(e,t,s)=>((e,t,s)=>t in e?l(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);const p=class e{constructor(e=5e3){this.pollingInterval=e,u(this,"events",new Map),u(this,"intervals",new Map),u(this,"handlerRegistry",new Map),this.restore()}static getInstance(t=5e3){return e.instance||(e.instance=new e(t)),e.instance}registerHandler(e,t){this.handlerRegistry.set(e,t),this.events.forEach((s,n)=>{s.event.type===e&&(this.stopPolling(n),s.handler=t,this.startPolling(n))})}add(e,t){const s=btoa(`${e}-${JSON.stringify(t)}`);this.events.has(s)&&this.remove(s);const n=this.handlerRegistry.get(e);if(!n)return;const i={key:s,type:e,params:t,createdAt:Date.now()};this.events.set(s,{event:i,handler:n}),this.persist(),this.startPolling(s)}remove(e){this.stopPolling(e),this.events.delete(e),this.persist()}startPolling(t){const s=this.events.get(t);if(!s)return;const{event:n,handler:i}=s,r=async()=>{try{if(n.createdAt&&Date.now()-n.createdAt>e.POLLING_TIMEOUT)return void this.remove(t);await i(n.params)&&this.remove(t)}catch(e){}};r();const a=window.setInterval(r,this.pollingInterval);this.intervals.set(t,a)}stopPolling(e){const t=this.intervals.get(e);void 0!==t&&(window.clearInterval(t),this.intervals.delete(e))}persist(){const t=Array.from(this.events.values()).map(e=>e.event);s.setItem(e.STORAGE_KEY,t)}restore(){const t=s.getItem(e.STORAGE_KEY);if(t&&Array.isArray(t)){const s=Date.now();t.forEach(t=>{if(t.createdAt&&s-t.createdAt>e.POLLING_TIMEOUT)return;const n=this.handlerRegistry.get(t.key);n?(this.events.set(t.key,{event:t,handler:n}),this.startPolling(t.key)):this.events.set(t.key,{event:t,handler:async()=>!1})})}}clear(){this.events.clear(),this.intervals.forEach(e=>window.clearInterval(e)),this.intervals.clear(),this.persist(),s.removeItem(e.STORAGE_KEY)}getEvents(){return Array.from(this.events.values()).map(e=>e.event)}};u(p,"EVENT_TYPES",{RESTORE_SESSION:"RESTORE_SESSION",TRACK_TX_STATUS:"TRACK_TX_STATUS",UPDATE_ACCOUNT:"UPDATE_ACCOUNT"}),u(p,"type"),u(p,"instance"),u(p,"STORAGE_KEY","c8-polling-events"),u(p,"POLLING_TIMEOUT",3e5);let m=p;var g=Object.defineProperty;class v{constructor(e){((e,t,s)=>{((e,t,s)=>{t in e?g(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s})(e,t+"",s)})(this,"baseUrl"),this.baseUrl=e.endsWith("/")?e.slice(0,-1):e}async request(e,t={}){const s=c.getInstance().getBearerToken(),n=c.getInstance().getAppName(),i=new Headers(t.headers);s&&(i.set("Authorization",`Bearer ${s}`),i.set("X-App-Name",null!=n?n:"Unknown App")),i.set("x-feat-decimals","1");const r=await fetch(`${this.baseUrl}${e}`,{...t,headers:i});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);return await r.json()}async getBalance(){return this.request("/api/balance")}async getTransferStatus(e){return this.request(`/api/transfer/status?command_id=${e}`)}}var T=Object.defineProperty,I=(e,t,s)=>((e,t,s)=>t in e?T(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);function f(){let e,t;return{promise:new Promise((s,n)=>{e=s,t=n}),resolve:e,reject:t}}class w{constructor(s,n,i=e){let r;switch(this.appName=s,this.appUrl=n,this.origin=i,I(this,"WINDOW_NAME","c8-wallet"),I(this,"WINDOW_WIDTH",475),I(this,"WINDOW_HEIGHT",762),I(this,"popup"),I(this,"sessionId",crypto.randomUUID()),I(this,"listening",!1),I(this,"walletReady",!1),I(this,"pending",new Map),I(this,"eventHandlers",new Set),I(this,"handshakeTimer"),I(this,"handshakeDeadline"),I(this,"closeWatcherTimer"),I(this,"pollingManager",m.getInstance()),I(this,"session",c.getInstance()),I(this,"initDeferred"),I(this,"httpClient"),this.onWindowMessage=this.onWindowMessage.bind(this),this.handleRestoreSession=this.handleRestoreSession.bind(this),this.handleTrackTxStatus=this.handleTrackTxStatus.bind(this),this.handleAccountUpdate=this.handleAccountUpdate.bind(this),this.session.setAppName(this.appName),this.attachListener(),this.origin){case e:r=t;break;case"https://wallet.cantor8.tech":case"https://wallet.main.digik.cantor8.tech":r="https://wallet-backend.main.cantor8.tech";break;default:r=t}this.httpClient=new v(r),this.pollingManager.registerHandler(m.EVENT_TYPES.RESTORE_SESSION,this.handleRestoreSession),this.pollingManager.registerHandler(m.EVENT_TYPES.TRACK_TX_STATUS,this.handleTrackTxStatus),this.pollingManager.registerHandler(m.EVENT_TYPES.UPDATE_ACCOUNT,this.handleAccountUpdate),this.checkRestoreSession()}checkRestoreSession(){this.session.hasStoredSession()&&this.pollingManager.add(m.EVENT_TYPES.RESTORE_SESSION,{sessionId:this.sessionId})}async handleAccountUpdate(e){try{const e=await this.httpClient.getBalance();if(e&&e.holdings){const t=[{partyId:e.party_id,holdings:Object.entries(e.holdings).map(([e,t])=>({instrumentId:e,balance:Number(t.balance),balanceUsd:Number(t.balance_usd)}))}];this.session.setAccounts(t),this.session.save()}return!0}catch(e){e instanceof Error&&e.message.includes("401")&&this.destroy()}return!1}async getTransferStatusById(e){try{const t=await this.httpClient.getTransferStatus(e);let s;switch(t.status){case"success":s="confirmed";break;case"failed":s="failed";break;default:s="pending"}return t.status=s,t}catch(e){return e instanceof Error&&e.message.includes("401")&&this.destroy(),null}}async handleTrackTxStatus(e){try{const t=await this.httpClient.getTransferStatus(e.txId);if(e.status!==t.status){let s;switch(t.status){case"success":s="confirmed";break;case"failed":s="failed";break;default:s="pending"}return this.emitSyntheticEvent({type:"txChanged",txId:e.txId,status:s}),e.status=t.status,this.pollingManager.persist(),"pending"!==t.status&&this.pollingManager.add(m.EVENT_TYPES.UPDATE_ACCOUNT,{txId:e.txId}),"success"===t.status||"failed"===t.status}}catch(t){if(t instanceof Error&&(t.message.includes("401")&&this.destroy(),t.message.includes("404")))return this.emitSyntheticEvent({type:"txChanged",txId:e.txId,status:"failed"}),!0}return!1}async handleRestoreSession(e){try{const e=await this.httpClient.getBalance();if(e&&e.holdings){const t=[{partyId:e.party_id,holdings:Object.entries(e.holdings).map(([e,t])=>({instrumentId:e,balance:Number(t.balance),balanceUsd:Number(t.balance_usd)}))}];this.session.setAccounts(t),this.session.save(),this.session.setConnected(!0),this.emitSyntheticEvent({type:"connected"});const s=this.session.getExpireAt();return s&&this.scheduleDisconnect(s),!0}}catch(e){e instanceof Error&&e.message.includes("401")&&this.destroy()}return!1}get WALLET_EMBEDDED(){return`${this.origin}/embedded/`}async init(e){var t;if(void 0!==this.popup&&(null==(t=this.popup)||!t.closed))return;if(this.initDeferred||(this.initDeferred=f()),this.listening||this.attachListener(),this.popup&&!this.popup.closed)return this.popup.focus(),null==this.handshakeTimer&&this.startHandshakeLoop(),this.initDeferred.promise;const s=new URL(null!=e?e:"",this.WALLET_EMBEDDED);if(this.popup=window.open(s,this.WINDOW_NAME,`width=${this.WINDOW_WIDTH},height=${this.WINDOW_HEIGHT}`),!this.popup){const e=new Error("Failed to open popup window");Object.assign(e,{code:"POPUP_BLOCKED",message:"browser blocked the popup window"}),this.rejectInit(e)}return this.startHandshakeLoop(),this.initDeferred.promise}emitSyntheticEvent(e){for(const t of this.eventHandlers)try{t({kind:"event",event:e})}catch(e){}}scheduleDisconnect(e){if(!e)return;const t=e-Date.now();if(t>0){const e=setTimeout(()=>{this.destroy("authToken expired")},t);this.session.setDisconnectTimeoutId(e)}else this.destroy("authToken expired")}destroy(e="destroyed"){try{this.emitSyntheticEvent({type:"disconnected",reason:e}),this.detachListener(),this.clearHandshakeLoop(),this.initDeferred&&(this.initDeferred.reject(new Error("Transport destroyed")),this.initDeferred=void 0);for(const[,e]of this.pending)e.reject(new Error("Transport destroyed"));this.pending.clear(),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=void 0,this.walletReady=!1,this.session.clear(),this.pollingManager.clear()}catch(e){}}async request(e,t,s){var n,i,r,a,o,h,d,c,l,u,p,m,g,v,T,I;const w=crypto.randomUUID(),E=f();this.pending.set(w,E);try{if("connect"===e){if(this.session.getBearerToken())return this.handleResponse({kind:"response",id:w,result:null}),E.promise;this.session.getBearerToken()||(this.walletReady=!1),await this.init()}if("send"===e&&(this.walletReady=!1,await this.init("confirmTransaction")),"signAndExecute"===e&&(this.walletReady=!1,await this.init("signAndExecute")),"status"===e)return this.handleResponse({kind:"response",id:w,result:{connected:this.session.getConnected(),walletVersion:void 0}}),E.promise;if(s&&(null==(n=this.popup)||n.focus()),"getInstruments"===e){const e=this.session.getInstruments();return this.handleResponse({kind:"response",id:w,result:{instruments:e}}),E.promise}if("getAccounts"===e){await this.handleAccountUpdate();const e=this.session.getAccounts();return this.handleResponse({kind:"response",id:w,result:{accounts:e}}),E.promise}if("checkTxStatusById"===e){const e=t,s=await this.getTransferStatusById(null==e?void 0:e.txId);if(s){const e={status:s.status,transfer:{senderPartyId:null!=(r=null==(i=s.transfer)?void 0:i.party_id)?r:"",receiverPartyId:null!=(o=null==(a=s.transfer)?void 0:a.party_id2)?o:"",amount:Number(null!=(d=null==(h=s.transfer)?void 0:h.amount)?d:"0"),networkFees:Number(null!=(l=null==(c=s.transfer)?void 0:c.network_fees)?l:"0"),instrumentId:null!=(p=null==(u=s.transfer)?void 0:u.instrument_id)?p:"",txId:null!=(g=null==(m=s.transfer)?void 0:m.command_id)?g:"",created_at:null!=(T=null==(v=s.transfer)?void 0:v.created_at)?T:"",memo:null==(I=s.transfer)?void 0:I.reason}};this.handleResponse({kind:"response",id:w,result:e})}else this.handleResponse({kind:"response",id:w,error:{code:"FAILED_TO_FETCH_TRANSFER_STATUS",message:"Failed to fetch transfer status"}});return E.promise}if("disconnect"===e)return this.handleResponse({kind:"response",id:w,result:null}),E.promise;const f={kind:"request",id:w,method:e,params:t,sessionId:this.sessionId};this.post(f)}catch(e){this.pending.delete(w),E.reject(e)}return E.promise}onEvent(e){return this.eventHandlers.add(e),()=>{this.eventHandlers.delete(e)}}attachListener(){this.listening||(window.addEventListener("message",this.onWindowMessage),this.listening=!0)}detachListener(){this.listening&&(window.removeEventListener("message",this.onWindowMessage),this.listening=!1)}post(e){try{if(!this.popup||this.popup.closed)return;this.popup.postMessage(e,this.origin)}catch(e){}}onWindowMessage(e){if(e.origin!==this.origin)return;const t=e.data;if(t&&"object"==typeof t){if("event"===t.kind){for(const e of this.eventHandlers)"txInitiated"===t.event.type&&this.pollingManager.add(m.EVENT_TYPES.TRACK_TX_STATUS,{txId:t.event.txId,status:"initiated"}),e(t);return}if("internal_event"===t.kind)return void this.pollingManager.add(t.event.type,{wop:"wopwop"});if("auth-flow"===t.kind&&(this.session.setBearerToken(t.token,t.expireAt),this.session.setAccounts(t.accounts),this.session.setInstruments(t.instruments),this.session.save(),this.scheduleDisconnect(t.expireAt)),"handshake-ack"===t.kind&&t.ok)return void this.handleHandshakeAck();"response"===t.kind&&this.handleResponse(t)}}handleHandshakeAck(){this.walletReady=!0,this.clearHandshakeLoop(),this.initDeferred&&(this.initDeferred.resolve(),this.initDeferred=void 0)}handleResponse(e){const t=this.pending.get(e.id);if(t)if(this.pending.delete(e.id),e.error){const s=new Error(e.error.message||"Unknown Error");Object.assign(s,{code:e.error.code,data:e.error.data}),t.reject(s)}else t.resolve(e.result)}startHandshakeLoop(){this.handshakeDeadline=Date.now()+55e3;const e=()=>{if(!this.walletReady)return!this.popup||this.popup.closed?(this.clearHandshakeLoop(),void this.rejectInit(new Error("Popup closed before handshake"))):this.handshakeDeadline&&Date.now()>this.handshakeDeadline?(this.clearHandshakeLoop(),void this.rejectInit(new Error("Handshake timed out"))):void this.post({kind:"handshake",sdkVersion:"0.0.0",sessionId:this.sessionId,dapp:{name:this.appName,url:this.appUrl}});this.clearHandshakeLoop()};e(),this.handshakeTimer=window.setInterval(e,300)}clearHandshakeLoop(){null!=this.handshakeTimer&&(clearInterval(this.handshakeTimer),this.handshakeTimer=void 0),this.handshakeDeadline=void 0}rejectInit(e){this.initDeferred&&(Object.assign(e,{code:"INITIALIZATION_FAILED",message:e.message}),this.initDeferred.reject(e),this.initDeferred=void 0)}startPopupClosedWatcher(){const e=this.popup;if(!e)return;const t=window.setInterval(()=>{(!e||e.closed)&&(clearInterval(t),this.destroy())},300);this.closeWatcherTimer=t}}var E=Object.defineProperty,y=(e,t,s)=>((e,t,s)=>t in e?E(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s);class k{constructor(t){var s,n,i;y(this,"transport"),y(this,"listeners",{});const r=null!=(s=t.dappName)?s:document.title||"Unknown dApp",a=null!=(n=t.dappUrl)?n:location.origin,o=null!=(i=t.network)?i:"mainnet";let h;if("devnet"!==o)throw new Error("Only devnet network is supported right now");if("devnet"!==o)throw new Error("Unsupported network: "+o);h=e,this.transport=new w(r,a,h),this.transport.onEvent(e=>{"event"===e.kind&&this.emit(e.event.type,e.event)})}async connect(){await this.transport.request("connect",void 0,!0)}async disconnect(){try{await this.transport.request("disconnect"),this.transport.destroy()}catch(e){}}status(){return this.transport.request("status")}getInstruments(){return this.transport.request("getInstruments")}getAccounts(e){return this.transport.request("getAccounts",{instrumentId:e})}send(e){return this.transport.request("send",e,!0)}signAndExecute(e){return this.transport.request("signAndExecute",e,!0)}signAndExecutePreparedTransfer(e){return this.transport.request("signAndExecutePreparedTransfer",e,!0)}acknowledge(e){return this.transport.request("acknowledge",e,!0)}checkTxStatusById(e){return this.transport.request("checkTxStatusById",e)}on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),()=>this.listeners[e].delete(t)}emit(e,t){var s;for(const n of null!=(s=this.listeners[e])?s:[])n(t)}}const S={uuid:"c8-wallet-connect",name:"C8 Wallet",icon:"",rdns:"tech.cantor8.wallet"},A="c8#provider_discovery";function b(e){const t={info:S,provider:e()};window.dispatchEvent(new CustomEvent(A,{detail:t}))}function C(e){const t=t=>{const s=t;s.detail&&e(s.detail.info,s.detail.provider)};return window.addEventListener(A,t),()=>window.removeEventListener(A,t)}export{k as C8WalletProvider,v as HttpClient,s as LocalStorageHelper,b as announceC8Provider,C as onC8ProviderDiscovered};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { C8EventByType, C8EventType, Listener } from "./types";
|
|
2
|
+
export declare class C8WalletProvider {
|
|
3
|
+
private transport;
|
|
4
|
+
private listeners;
|
|
5
|
+
constructor(opts: {
|
|
6
|
+
dappName: string;
|
|
7
|
+
dappUrl?: string;
|
|
8
|
+
network?: "devnet" | "mainnet" | "local";
|
|
9
|
+
});
|
|
10
|
+
connect(): Promise<void>;
|
|
11
|
+
disconnect(): Promise<void>;
|
|
12
|
+
status(): Promise<{
|
|
13
|
+
connected: boolean;
|
|
14
|
+
walletVersion?: string;
|
|
15
|
+
}>;
|
|
16
|
+
getInstruments(): Promise<import("./types").InstrumentListPayload>;
|
|
17
|
+
getAccounts(instrumentId?: string): Promise<import("./types").AccountListPayload>;
|
|
18
|
+
send(input: {
|
|
19
|
+
senderPartyId: string;
|
|
20
|
+
instrumentId: string;
|
|
21
|
+
amount: number;
|
|
22
|
+
receiverPartyId: string;
|
|
23
|
+
memo?: string;
|
|
24
|
+
metadata?: Record<string, string>;
|
|
25
|
+
}): Promise<import("./types").SubmitTransferResultPayload>;
|
|
26
|
+
signAndExecute(input: {
|
|
27
|
+
note: string;
|
|
28
|
+
partyId: string;
|
|
29
|
+
commandId: string;
|
|
30
|
+
commandsJson: string;
|
|
31
|
+
disclosedContracts: string[];
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
private signAndExecutePreparedTransfer;
|
|
34
|
+
private acknowledge;
|
|
35
|
+
checkTxStatusById(input: {
|
|
36
|
+
txId: string;
|
|
37
|
+
}): Promise<import("./types").TransferStatusResponsePayload>;
|
|
38
|
+
on<T extends C8EventType>(event: T, cb: Listener<C8EventByType<T>>): () => boolean;
|
|
39
|
+
private emit;
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AccountInfoPayload, InstrumentInfoPayload } from "./types";
|
|
2
|
+
declare class Session {
|
|
3
|
+
private static instance;
|
|
4
|
+
static readonly SESSION_KEY = "c8-session";
|
|
5
|
+
private appName;
|
|
6
|
+
private accounts;
|
|
7
|
+
private instruments;
|
|
8
|
+
private partyIds;
|
|
9
|
+
private authToken;
|
|
10
|
+
private isConnected;
|
|
11
|
+
private expireAt;
|
|
12
|
+
private disconnectTimeoutId;
|
|
13
|
+
private constructor();
|
|
14
|
+
static getInstance(): Session;
|
|
15
|
+
setAppName(appName: string): void;
|
|
16
|
+
getAppName(): string | undefined;
|
|
17
|
+
setInstruments(instruments: InstrumentInfoPayload[]): void;
|
|
18
|
+
getInstruments(): InstrumentInfoPayload[];
|
|
19
|
+
setAccounts(accounts: AccountInfoPayload[]): void;
|
|
20
|
+
getAccounts(): AccountInfoPayload[];
|
|
21
|
+
setBearerToken(token: string | null, expireAt: number | null): void;
|
|
22
|
+
getExpireAt(): number | null;
|
|
23
|
+
setDisconnectTimeoutId(id: any): void;
|
|
24
|
+
getDisconnectTimeoutId(): any;
|
|
25
|
+
getBearerToken(): string | null;
|
|
26
|
+
clear(): void;
|
|
27
|
+
save(): void;
|
|
28
|
+
setConnected(isConnected: boolean): void;
|
|
29
|
+
getConnected(): boolean;
|
|
30
|
+
hasStoredSession(): boolean;
|
|
31
|
+
private load;
|
|
32
|
+
}
|
|
33
|
+
export default Session;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { Transport } from "./transports/Transport";
|
|
2
|
+
export { WindowTransport } from "./transports/WindowTransport";
|
|
3
|
+
export { ThinTransport } from "./transports/ThinTransport";
|
|
4
|
+
export { IFrameTransport } from "./transports/IFrameTransport";
|
|
5
|
+
export { WebViewTransport } from "./transports/WebViewTransport";
|
|
6
|
+
export { WALLET_EMBED_URL, WALLET_ORIGIN_MAINNET, WALLET_ORIGIN_DEVNET } from "./transports/constants";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { InboundMessage, WalletMethod } from "../types";
|
|
2
|
+
import type { Transport } from "./Transport";
|
|
3
|
+
/**
|
|
4
|
+
* IFrameTransport embeds the wallet into the current page via an <iframe>
|
|
5
|
+
* and communicates with it using window.postMessage. This avoids popups
|
|
6
|
+
* and provides a persistent, same-tab experience.
|
|
7
|
+
*/
|
|
8
|
+
export declare class IFrameTransport implements Transport {
|
|
9
|
+
private readonly dappName;
|
|
10
|
+
private readonly dappUrl;
|
|
11
|
+
private readonly origin;
|
|
12
|
+
/**
|
|
13
|
+
* Optional target where the iframe should be appended. If a function is provided
|
|
14
|
+
* it will be called at init-time to resolve the element. Defaults to document.body.
|
|
15
|
+
*/
|
|
16
|
+
private readonly appendTarget?;
|
|
17
|
+
private iframe?;
|
|
18
|
+
private readonly sessionId;
|
|
19
|
+
private listening;
|
|
20
|
+
private walletReady;
|
|
21
|
+
private readonly pending;
|
|
22
|
+
private readonly eventHandlers;
|
|
23
|
+
private handshakeTimer?;
|
|
24
|
+
private handshakeDeadline?;
|
|
25
|
+
private initDeferred?;
|
|
26
|
+
constructor(dappName: string, dappUrl: string, origin?: string,
|
|
27
|
+
/**
|
|
28
|
+
* Optional target where the iframe should be appended. If a function is provided
|
|
29
|
+
* it will be called at init-time to resolve the element. Defaults to document.body.
|
|
30
|
+
*/
|
|
31
|
+
appendTarget?: (Element | (() => Element | null)) | undefined);
|
|
32
|
+
private get WALLET_EMBEDDED();
|
|
33
|
+
init(): Promise<void>;
|
|
34
|
+
destroy(): void;
|
|
35
|
+
request<M extends WalletMethod, T = unknown>(method: M, params?: unknown, _forceShow?: boolean): Promise<T>;
|
|
36
|
+
onEvent(cb: (msg: InboundMessage) => void): () => void;
|
|
37
|
+
private attachListener;
|
|
38
|
+
private detachListener;
|
|
39
|
+
private post;
|
|
40
|
+
private onWindowMessage;
|
|
41
|
+
private handleHandshakeAck;
|
|
42
|
+
private handleResponse;
|
|
43
|
+
private startHandshakeLoop;
|
|
44
|
+
private clearHandshakeLoop;
|
|
45
|
+
private rejectInit;
|
|
46
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { InboundMessage, WalletMethod } from "../types";
|
|
2
|
+
import type { Transport } from "./Transport";
|
|
3
|
+
/**
|
|
4
|
+
* ThinTransport is used when both dApp and Wallet run within the same page context
|
|
5
|
+
* (e.g., wallet is embedded in an iframe and exposes the SDK). Communication is
|
|
6
|
+
* direct via postMessage with a provided target window and origin. No popup or
|
|
7
|
+
* window management is performed here.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ThinTransport implements Transport {
|
|
10
|
+
private readonly appName;
|
|
11
|
+
private readonly appUrl;
|
|
12
|
+
private readonly targetOrigin;
|
|
13
|
+
private readonly targetWindow;
|
|
14
|
+
private readonly sessionId;
|
|
15
|
+
private listening;
|
|
16
|
+
private walletReady;
|
|
17
|
+
private readonly pending;
|
|
18
|
+
private readonly eventHandlers;
|
|
19
|
+
private handshakeTimer?;
|
|
20
|
+
private handshakeDeadline?;
|
|
21
|
+
private initDeferred?;
|
|
22
|
+
constructor(appName: string, appUrl: string, targetOrigin: string, targetWindow: Window | null | undefined);
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
destroy(): void;
|
|
25
|
+
request<M extends WalletMethod, T = unknown>(method: M, params?: unknown, _forceShow?: boolean): Promise<T>;
|
|
26
|
+
onEvent(cb: (msg: InboundMessage) => void): () => void;
|
|
27
|
+
private attachListener;
|
|
28
|
+
private detachListener;
|
|
29
|
+
private post;
|
|
30
|
+
private onWindowMessage;
|
|
31
|
+
private handleHandshakeAck;
|
|
32
|
+
private handleResponse;
|
|
33
|
+
private startHandshakeLoop;
|
|
34
|
+
private clearHandshakeLoop;
|
|
35
|
+
private rejectInit;
|
|
36
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InboundMessage, WalletMethod, WalletRequestPayloadMap, WalletResponsePayloadMap } from "../types";
|
|
2
|
+
export interface Transport {
|
|
3
|
+
init(): Promise<void>;
|
|
4
|
+
destroy(): void;
|
|
5
|
+
request<M extends WalletMethod>(method: M, params?: WalletRequestPayloadMap[M], forceShow?: boolean): Promise<WalletResponsePayloadMap[M]>;
|
|
6
|
+
onEvent(cb: (msg: InboundMessage) => void): () => void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { InboundMessage, WalletMethod } from "../types";
|
|
2
|
+
import type { Transport } from "./Transport";
|
|
3
|
+
/**
|
|
4
|
+
* WebViewTransport (WebView-only)
|
|
5
|
+
* Runs INSIDE the WebView page (dApp side) and talks to the native app via:
|
|
6
|
+
* - web -> native: window.ReactNativeWebView.postMessage(string)
|
|
7
|
+
* - native -> web: "message" events (window + document), payload is usually string
|
|
8
|
+
*
|
|
9
|
+
* Assumptions:
|
|
10
|
+
* - We do NOT support iframe/popup/window.opener here (webview only).
|
|
11
|
+
* - We do NOT use WKWebView messageHandlers / AndroidInterface hooks here.
|
|
12
|
+
*/
|
|
13
|
+
export declare class WebViewTransport implements Transport {
|
|
14
|
+
private readonly dappName;
|
|
15
|
+
private readonly dappUrl;
|
|
16
|
+
private readonly sessionId;
|
|
17
|
+
private listening;
|
|
18
|
+
private walletReady;
|
|
19
|
+
private readonly pending;
|
|
20
|
+
private readonly eventHandlers;
|
|
21
|
+
private handshakeTimer?;
|
|
22
|
+
private handshakeDeadline?;
|
|
23
|
+
private initDeferred?;
|
|
24
|
+
constructor(dappName: string, dappUrl: string);
|
|
25
|
+
init(): Promise<void>;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
request<M extends WalletMethod, T = unknown>(method: M, params?: unknown): Promise<T>;
|
|
28
|
+
onEvent(cb: (msg: InboundMessage) => void): () => void;
|
|
29
|
+
private attachListener;
|
|
30
|
+
private detachListener;
|
|
31
|
+
private onMessageEvent;
|
|
32
|
+
private processInboundMessage;
|
|
33
|
+
private handleHandshakeAck;
|
|
34
|
+
private handleResponse;
|
|
35
|
+
private postToNative;
|
|
36
|
+
private startHandshakeLoop;
|
|
37
|
+
private clearHandshakeLoop;
|
|
38
|
+
private rejectInit;
|
|
39
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { InboundMessage, WalletMethod, WalletRequestPayload } from "../types";
|
|
2
|
+
import type { Transport } from "./Transport";
|
|
3
|
+
export declare class WindowTransport implements Transport {
|
|
4
|
+
private readonly appName;
|
|
5
|
+
private readonly appUrl;
|
|
6
|
+
private readonly origin;
|
|
7
|
+
private WINDOW_NAME;
|
|
8
|
+
private WINDOW_WIDTH;
|
|
9
|
+
private WINDOW_HEIGHT;
|
|
10
|
+
private popup?;
|
|
11
|
+
private readonly sessionId;
|
|
12
|
+
private listening;
|
|
13
|
+
private walletReady;
|
|
14
|
+
private readonly pending;
|
|
15
|
+
private readonly eventHandlers;
|
|
16
|
+
private handshakeTimer?;
|
|
17
|
+
private handshakeDeadline?;
|
|
18
|
+
private closeWatcherTimer?;
|
|
19
|
+
private pollingManager;
|
|
20
|
+
private session;
|
|
21
|
+
private initDeferred?;
|
|
22
|
+
private httpClient;
|
|
23
|
+
constructor(appName: string, appUrl: string, origin?: string);
|
|
24
|
+
private checkRestoreSession;
|
|
25
|
+
private handleAccountUpdate;
|
|
26
|
+
private getTransferStatusById;
|
|
27
|
+
private handleTrackTxStatus;
|
|
28
|
+
private handleRestoreSession;
|
|
29
|
+
private get WALLET_EMBEDDED();
|
|
30
|
+
init(path?: string): Promise<void>;
|
|
31
|
+
private emitSyntheticEvent;
|
|
32
|
+
private scheduleDisconnect;
|
|
33
|
+
destroy(reason?: string): void;
|
|
34
|
+
request<M extends WalletMethod, T = unknown>(method: M, params?: WalletRequestPayload<M>, forceShow?: boolean): Promise<T>;
|
|
35
|
+
onEvent(cb: (msg: InboundMessage) => void): () => void;
|
|
36
|
+
private attachListener;
|
|
37
|
+
private detachListener;
|
|
38
|
+
private post;
|
|
39
|
+
private onWindowMessage;
|
|
40
|
+
private handleHandshakeAck;
|
|
41
|
+
private handleResponse;
|
|
42
|
+
private startHandshakeLoop;
|
|
43
|
+
private clearHandshakeLoop;
|
|
44
|
+
private rejectInit;
|
|
45
|
+
private startPopupClosedWatcher;
|
|
46
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const WALLET_ORIGIN_LOCAL = "http://localhost:8081";
|
|
2
|
+
export declare const WALLET_ORIGIN_DEVNET = "https://wallet.dev.digik.cantor8.tech";
|
|
3
|
+
export declare const WALLET_API_DEVNET = "https://wallet-backend.dev.digik.cantor8.tech";
|
|
4
|
+
export declare const WALLET_ORIGIN_MAINNET = "https://wallet.cantor8.tech";
|
|
5
|
+
export declare const WALLET_API_MAINNET = "https://wallet-backend.main.cantor8.tech";
|
|
6
|
+
export declare const WALLET_ORIGIN_TEST_MAINNET = "https://wallet.main.digik.cantor8.tech";
|
|
7
|
+
export declare const WALLET_EMBED_URL = "/embedded";
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export type Json = null | boolean | number | string | Json[] | {
|
|
2
|
+
[k: string]: Json;
|
|
3
|
+
};
|
|
4
|
+
export type RpcError = {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
data?: Json;
|
|
8
|
+
};
|
|
9
|
+
export type Listener<T extends C8Event> = (event: T) => void;
|
|
10
|
+
export type C8Event = {
|
|
11
|
+
type: "connected";
|
|
12
|
+
meta?: Json;
|
|
13
|
+
} | {
|
|
14
|
+
type: "disconnected";
|
|
15
|
+
reason?: string;
|
|
16
|
+
meta?: Json;
|
|
17
|
+
} | {
|
|
18
|
+
type: "txInitiated";
|
|
19
|
+
txId?: string;
|
|
20
|
+
meta?: Json;
|
|
21
|
+
} | {
|
|
22
|
+
type: "txChanged";
|
|
23
|
+
txId: string;
|
|
24
|
+
status: "pending" | "confirmed" | "failed" | string;
|
|
25
|
+
meta?: Json;
|
|
26
|
+
} | {
|
|
27
|
+
type: "themeChanged";
|
|
28
|
+
theme: "dark" | "light";
|
|
29
|
+
meta?: Json;
|
|
30
|
+
} | {
|
|
31
|
+
type: "operationCanceled";
|
|
32
|
+
reason: string;
|
|
33
|
+
meta?: Json;
|
|
34
|
+
} | {
|
|
35
|
+
type: "accountChanged";
|
|
36
|
+
accounts: AccountInfoPayload[];
|
|
37
|
+
meta?: Json;
|
|
38
|
+
};
|
|
39
|
+
export type C8EventType = C8Event["type"];
|
|
40
|
+
export type C8EventByType<T extends C8EventType> = Extract<C8Event, {
|
|
41
|
+
type: T;
|
|
42
|
+
}>;
|
|
43
|
+
export type OutboundMessage<M extends WalletMethod = WalletMethod> = {
|
|
44
|
+
kind: "handshake";
|
|
45
|
+
sdkVersion: string;
|
|
46
|
+
sessionId: string;
|
|
47
|
+
dapp: {
|
|
48
|
+
name: string;
|
|
49
|
+
url: string;
|
|
50
|
+
};
|
|
51
|
+
} | {
|
|
52
|
+
kind: "request";
|
|
53
|
+
id: string;
|
|
54
|
+
method: M;
|
|
55
|
+
params: WalletRequestPayload<M>;
|
|
56
|
+
sessionId: string;
|
|
57
|
+
};
|
|
58
|
+
export type InboundMessage = {
|
|
59
|
+
kind: "handshake-ack";
|
|
60
|
+
ok: true;
|
|
61
|
+
walletVersion: string;
|
|
62
|
+
} | {
|
|
63
|
+
kind: "response";
|
|
64
|
+
id: string;
|
|
65
|
+
result?: Json;
|
|
66
|
+
error?: RpcError;
|
|
67
|
+
} | {
|
|
68
|
+
kind: "event";
|
|
69
|
+
event: C8Event;
|
|
70
|
+
} | {
|
|
71
|
+
kind: "auth-flow";
|
|
72
|
+
token: string;
|
|
73
|
+
expireAt: number;
|
|
74
|
+
accounts: AccountInfoPayload[];
|
|
75
|
+
instruments: InstrumentInfoPayload[];
|
|
76
|
+
} | {
|
|
77
|
+
kind: "internal_event";
|
|
78
|
+
event: {
|
|
79
|
+
type: string;
|
|
80
|
+
payload: any;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export type WalletMethod = "connect" | "disconnect" | "status" | "getInstruments" | "getAccounts" | "send" | "signAndExecute" | "signAndExecutePreparedTransfer" | "acknowledge" | "checkTxStatusById";
|
|
84
|
+
export interface WalletRequestPayloadMap {
|
|
85
|
+
connect: undefined;
|
|
86
|
+
disconnect: undefined;
|
|
87
|
+
status: undefined;
|
|
88
|
+
getInstruments: undefined;
|
|
89
|
+
getAccounts: {
|
|
90
|
+
instrumentId?: string;
|
|
91
|
+
};
|
|
92
|
+
send: {
|
|
93
|
+
senderPartyId: string;
|
|
94
|
+
instrumentId: string;
|
|
95
|
+
amount: number;
|
|
96
|
+
receiverPartyId: string;
|
|
97
|
+
memo?: string;
|
|
98
|
+
metadata?: Record<string, string>;
|
|
99
|
+
};
|
|
100
|
+
signAndExecute: {
|
|
101
|
+
note: string;
|
|
102
|
+
partyId: string;
|
|
103
|
+
commandId: string;
|
|
104
|
+
commandsJson: string;
|
|
105
|
+
disclosedContracts: string[];
|
|
106
|
+
};
|
|
107
|
+
signAndExecutePreparedTransfer: {
|
|
108
|
+
partyId: string;
|
|
109
|
+
commandId: string;
|
|
110
|
+
preparedTxB64: string;
|
|
111
|
+
hashB64: string;
|
|
112
|
+
hashingSchemeVersion: string;
|
|
113
|
+
fees?: TransferFee[];
|
|
114
|
+
totalFee?: number;
|
|
115
|
+
};
|
|
116
|
+
acknowledge: {
|
|
117
|
+
partyId: string;
|
|
118
|
+
txId: string;
|
|
119
|
+
};
|
|
120
|
+
checkTxStatusById: {
|
|
121
|
+
txId: string;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export type WalletRequestPayload<M extends WalletMethod> = WalletRequestPayloadMap[M];
|
|
125
|
+
export interface TransferTransactionPayload {
|
|
126
|
+
senderPartyId: string;
|
|
127
|
+
receiverPartyId: string;
|
|
128
|
+
amount: number;
|
|
129
|
+
networkFees: number;
|
|
130
|
+
instrumentId: string;
|
|
131
|
+
txId: string;
|
|
132
|
+
created_at?: string | null;
|
|
133
|
+
memo?: string | null;
|
|
134
|
+
}
|
|
135
|
+
export interface TransferStatusResponsePayload {
|
|
136
|
+
status: string;
|
|
137
|
+
transfer: TransferTransactionPayload | null;
|
|
138
|
+
}
|
|
139
|
+
export interface SubmitTransferResultPayload {
|
|
140
|
+
txId: string;
|
|
141
|
+
}
|
|
142
|
+
export interface AppConfigPayload {
|
|
143
|
+
min_supported_version: string;
|
|
144
|
+
latest_version: string;
|
|
145
|
+
update_url_ios?: string | null;
|
|
146
|
+
update_url_android?: string | null;
|
|
147
|
+
signups_guarded?: boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface AccountInfoHolding {
|
|
150
|
+
instrumentId: string;
|
|
151
|
+
balance: number;
|
|
152
|
+
balanceUsd: number;
|
|
153
|
+
}
|
|
154
|
+
export interface AccountInfoPayload {
|
|
155
|
+
accountName?: string;
|
|
156
|
+
partyId: string;
|
|
157
|
+
holdings: AccountInfoHolding[];
|
|
158
|
+
}
|
|
159
|
+
export interface AccountListPayload {
|
|
160
|
+
accounts: AccountInfoPayload[];
|
|
161
|
+
}
|
|
162
|
+
export interface TransferHistoryResponsePayload {
|
|
163
|
+
transfers: TransferTransactionPayload[];
|
|
164
|
+
}
|
|
165
|
+
export interface TokenOfferPayload {
|
|
166
|
+
contractId: string;
|
|
167
|
+
senderPartyId: string;
|
|
168
|
+
instrumentId: string;
|
|
169
|
+
amount: number;
|
|
170
|
+
}
|
|
171
|
+
export interface TransferFee {
|
|
172
|
+
amount: number;
|
|
173
|
+
receiverPartyId: string;
|
|
174
|
+
description: string;
|
|
175
|
+
instrumentId: string | null;
|
|
176
|
+
}
|
|
177
|
+
export interface TokenOffersPayload {
|
|
178
|
+
offers: TokenOfferPayload[];
|
|
179
|
+
}
|
|
180
|
+
export interface InstrumentInfoPayload {
|
|
181
|
+
instrumentId: string;
|
|
182
|
+
name: string;
|
|
183
|
+
symbol: string;
|
|
184
|
+
}
|
|
185
|
+
export interface InstrumentListPayload {
|
|
186
|
+
instruments: InstrumentInfoPayload[];
|
|
187
|
+
}
|
|
188
|
+
export interface WalletResponsePayloadMap {
|
|
189
|
+
connect: void;
|
|
190
|
+
disconnect: void;
|
|
191
|
+
status: {
|
|
192
|
+
connected: boolean;
|
|
193
|
+
walletVersion?: string;
|
|
194
|
+
};
|
|
195
|
+
getInstruments: InstrumentListPayload;
|
|
196
|
+
getAccounts: AccountListPayload;
|
|
197
|
+
send: SubmitTransferResultPayload;
|
|
198
|
+
signAndExecute: void;
|
|
199
|
+
signAndExecutePreparedTransfer: SubmitTransferResultPayload;
|
|
200
|
+
acknowledge: {
|
|
201
|
+
success: boolean;
|
|
202
|
+
};
|
|
203
|
+
checkTxStatusById: TransferStatusResponsePayload;
|
|
204
|
+
}
|
|
205
|
+
export type WalletResponsePayload<M extends WalletMethod> = WalletResponsePayloadMap[M];
|
|
206
|
+
export type PollingHandler = (params: any) => Promise<boolean>;
|
|
207
|
+
export interface PollingEvent {
|
|
208
|
+
key: string;
|
|
209
|
+
type: string;
|
|
210
|
+
params: any;
|
|
211
|
+
createdAt?: number;
|
|
212
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PartyHoldingsApiResponse, TransferTransactionApiResponse } from "./HttpClient.types";
|
|
2
|
+
export declare class HttpClient {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
constructor(baseUrl: string);
|
|
5
|
+
private request;
|
|
6
|
+
getBalance(): Promise<PartyHoldingsApiResponse>;
|
|
7
|
+
getTransferStatus(txId: string): Promise<TransferTransactionApiResponse>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface TransferTransactionApiResponse {
|
|
2
|
+
status: string;
|
|
3
|
+
transfer: TransferTransactionApiPayload;
|
|
4
|
+
}
|
|
5
|
+
export interface TransferTransactionApiPayload {
|
|
6
|
+
party_id: string;
|
|
7
|
+
party_id2: string;
|
|
8
|
+
direction: "OUT" | "IN";
|
|
9
|
+
amount: string;
|
|
10
|
+
network_fees: string;
|
|
11
|
+
instrument_id: string;
|
|
12
|
+
reason: string | null;
|
|
13
|
+
execute_before: string | null;
|
|
14
|
+
final_update_id: string | null;
|
|
15
|
+
update_id: string;
|
|
16
|
+
command_id: string;
|
|
17
|
+
ledger_offset: number;
|
|
18
|
+
record_time: string;
|
|
19
|
+
created_at: string;
|
|
20
|
+
metadata: Record<string, string>;
|
|
21
|
+
status: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface HoldingDetails {
|
|
24
|
+
instrument_admin_id: string;
|
|
25
|
+
balance: string;
|
|
26
|
+
balance_usd: string;
|
|
27
|
+
}
|
|
28
|
+
export interface PartyHoldingsApiResponse {
|
|
29
|
+
party_id: string;
|
|
30
|
+
holdings: Record<string, HoldingDetails>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PollingEvent, PollingHandler } from "../types";
|
|
2
|
+
export declare class PollingManager {
|
|
3
|
+
private pollingInterval;
|
|
4
|
+
static readonly EVENT_TYPES: {
|
|
5
|
+
readonly RESTORE_SESSION: "RESTORE_SESSION";
|
|
6
|
+
readonly TRACK_TX_STATUS: "TRACK_TX_STATUS";
|
|
7
|
+
readonly UPDATE_ACCOUNT: "UPDATE_ACCOUNT";
|
|
8
|
+
};
|
|
9
|
+
static type: typeof PollingManager.EVENT_TYPES[keyof typeof PollingManager.EVENT_TYPES];
|
|
10
|
+
private static instance;
|
|
11
|
+
private static readonly STORAGE_KEY;
|
|
12
|
+
private static readonly POLLING_TIMEOUT;
|
|
13
|
+
private events;
|
|
14
|
+
private intervals;
|
|
15
|
+
private handlerRegistry;
|
|
16
|
+
private constructor();
|
|
17
|
+
static getInstance(pollingInterval?: number): PollingManager;
|
|
18
|
+
registerHandler(type: string, handler: PollingHandler): void;
|
|
19
|
+
add(type: string, params: any): void;
|
|
20
|
+
remove(key: string): void;
|
|
21
|
+
private startPolling;
|
|
22
|
+
private stopPolling;
|
|
23
|
+
persist(): void;
|
|
24
|
+
restore(): void;
|
|
25
|
+
clear(): void;
|
|
26
|
+
getEvents(): PollingEvent[];
|
|
27
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare class LocalStorageHelper {
|
|
2
|
+
/**
|
|
3
|
+
* Get item from localStorage
|
|
4
|
+
* @param key
|
|
5
|
+
* @returns {T | null}
|
|
6
|
+
*/
|
|
7
|
+
static getItem<T>(key: string): T | null;
|
|
8
|
+
/**
|
|
9
|
+
* Set item in localStorage
|
|
10
|
+
* @param key
|
|
11
|
+
* @param value
|
|
12
|
+
*/
|
|
13
|
+
static setItem<T>(key: string, value: T): void;
|
|
14
|
+
/**
|
|
15
|
+
* Remove item from localStorage
|
|
16
|
+
* @param key
|
|
17
|
+
*/
|
|
18
|
+
static removeItem(key: string): void;
|
|
19
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cantor8/wallet-connect-sdk",
|
|
3
|
+
"version": "0.3.0-alpha.1",
|
|
4
|
+
"description": "C8 Wallet Connect SDK for dApp developers: postMessage API to interact with C8 Wallet.",
|
|
5
|
+
"author": "C8 / Cantor8",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"module": "./dist/index.esm.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"browser": "./dist/index.esm.js",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.esm.js",
|
|
17
|
+
"require": "./dist/index.cjs",
|
|
18
|
+
"default": "./dist/index.esm.js"
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/**/*.js",
|
|
24
|
+
"dist/**/*.cjs",
|
|
25
|
+
"dist/**/*.d.ts",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"build": "npm run clean && rollup -c && tsc --emitDeclarationOnly",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"prepare": "npm run build",
|
|
33
|
+
"pack": "npm run build && npm pack"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"wallet",
|
|
37
|
+
"connect",
|
|
38
|
+
"canton",
|
|
39
|
+
"c8",
|
|
40
|
+
"dapp",
|
|
41
|
+
"sdk"
|
|
42
|
+
],
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
45
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
46
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
47
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
48
|
+
"rollup": "^4.60.2",
|
|
49
|
+
"rollup-plugin-esbuild": "^6.1.0",
|
|
50
|
+
"typescript": "^6.0.3"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"registry": "https://registry.npmjs.org/"
|
|
54
|
+
}
|
|
55
|
+
}
|