feat: add account change notifications
This commit is contained in:
parent
9839c087d7
commit
e7097340f2
|
@ -23,4 +23,4 @@ lib
|
||||||
doc
|
doc
|
||||||
|
|
||||||
# VIM swap files
|
# VIM swap files
|
||||||
*.sw.
|
*.sw*
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
// flow-typed signature: 31b3dc13d06052ea505e8da9ca72c537
|
||||||
|
// flow-typed version: <<STUB>>/rpc-websockets_v4.3.3/flow_v0.84.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an autogenerated libdef stub for:
|
||||||
|
*
|
||||||
|
* 'rpc-websockets'
|
||||||
|
*
|
||||||
|
* Fill this stub out by replacing all the `any` types.
|
||||||
|
*
|
||||||
|
* Once filled out, we encourage you to share your work with the
|
||||||
|
* community by sending a pull request to:
|
||||||
|
* https://github.com/flowtype/flow-typed
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module 'rpc-websockets' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We include stubs for each file inside this npm package in case you need to
|
||||||
|
* require those files directly. Feel free to delete any files that aren't
|
||||||
|
* needed.
|
||||||
|
*/
|
||||||
|
declare module 'rpc-websockets/dist/index.browser-bundle' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/index.browser' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/index' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/client' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/client/websocket.browser' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/client/websocket' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/handler' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/server' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'rpc-websockets/dist/lib/utils' {
|
||||||
|
declare module.exports: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filename aliases
|
||||||
|
declare module 'rpc-websockets/dist/index.browser-bundle.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/index.browser-bundle'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/index.browser.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/index.browser'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/index.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/index'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/client.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/client'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/client/websocket.browser.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/client/websocket.browser'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/client/websocket.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/client/websocket'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/handler.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/handler'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/server.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/server'>;
|
||||||
|
}
|
||||||
|
declare module 'rpc-websockets/dist/lib/utils.js' {
|
||||||
|
declare module.exports: $Exports<'rpc-websockets/dist/lib/utils'>;
|
||||||
|
}
|
|
@ -41,6 +41,8 @@ declare module '@solana/web3.js' {
|
||||||
userdata: Buffer,
|
userdata: Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare type AccountChangeCallback = (accountInfo: AccountInfo) => void;
|
||||||
|
|
||||||
declare export type SignatureStatus = 'Confirmed'
|
declare export type SignatureStatus = 'Confirmed'
|
||||||
| 'AccountInUse'
|
| 'AccountInUse'
|
||||||
| 'SignatureNotFound'
|
| 'SignatureNotFound'
|
||||||
|
@ -58,6 +60,8 @@ declare module '@solana/web3.js' {
|
||||||
getFinality(): Promise<number>;
|
getFinality(): Promise<number>;
|
||||||
requestAirdrop(to: PublicKey, amount: number): Promise<TransactionSignature>;
|
requestAirdrop(to: PublicKey, amount: number): Promise<TransactionSignature>;
|
||||||
sendTransaction(from: Account, transaction: Transaction): Promise<TransactionSignature>;
|
sendTransaction(from: Account, transaction: Transaction): Promise<TransactionSignature>;
|
||||||
|
onAccountChange(publickey: PublicKey, callback: AccountChangeCallback): Promise<number>;
|
||||||
|
removeAccountListener(id: number): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === src/system-program.js ===
|
// === src/system-program.js ===
|
||||||
|
|
|
@ -4,6 +4,23 @@
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"101": {
|
||||||
|
"version": "1.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/101/-/101-1.6.3.tgz",
|
||||||
|
"integrity": "sha512-4dmQ45yY0Dx24Qxp+zAsNLlMF6tteCyfVzgbulvSyC7tCyd3V8sW76sS0tHq8NpcbXfWTKasfyfzU1Kd86oKzw==",
|
||||||
|
"requires": {
|
||||||
|
"clone": "1.0.4",
|
||||||
|
"deep-eql": "0.1.3",
|
||||||
|
"keypather": "1.10.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"clone": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||||
|
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
"version": "7.0.0-beta.44",
|
"version": "7.0.0-beta.44",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
|
||||||
|
@ -917,6 +934,19 @@
|
||||||
"minimalistic-assert": "1.0.1"
|
"minimalistic-assert": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"assert-args": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/assert-args/-/assert-args-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-QEEDoUUqMv53iYgR5U5ZCoqTc70=",
|
||||||
|
"requires": {
|
||||||
|
"101": "1.6.3",
|
||||||
|
"compound-subject": "0.0.1",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"get-prototype-of": "0.0.0",
|
||||||
|
"is-capitalized": "1.0.0",
|
||||||
|
"is-class": "0.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"assert-plus": {
|
"assert-plus": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||||
|
@ -947,8 +977,7 @@
|
||||||
"async-limiter": {
|
"async-limiter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
|
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
|
@ -2964,6 +2993,11 @@
|
||||||
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
|
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"compound-subject": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/compound-subject/-/compound-subject-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-JxVUaYoVrmCLHfyv0wt7oeqJLEs="
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
@ -3277,7 +3311,6 @@
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -3321,6 +3354,14 @@
|
||||||
"mimic-response": "1.0.1"
|
"mimic-response": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"deep-eql": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
|
||||||
|
"integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "0.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"deep-extend": {
|
"deep-extend": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
|
@ -4631,6 +4672,11 @@
|
||||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"eventemitter3": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA=="
|
||||||
|
},
|
||||||
"evp_bytestokey": {
|
"evp_bytestokey": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||||
|
@ -6077,6 +6123,11 @@
|
||||||
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
|
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"get-prototype-of": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-prototype-of/-/get-prototype-of-0.0.0.tgz",
|
||||||
|
"integrity": "sha1-mHcr0QcW0W3rSzIlFsRp78oorEQ="
|
||||||
|
},
|
||||||
"get-stdin": {
|
"get-stdin": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||||
|
@ -6866,6 +6917,11 @@
|
||||||
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
|
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-capitalized": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-capitalized/-/is-capitalized-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-TIRktNkdPk7rRIid0s2PGwrEwTY="
|
||||||
|
},
|
||||||
"is-ci": {
|
"is-ci": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
|
||||||
|
@ -6875,6 +6931,11 @@
|
||||||
"ci-info": "1.1.3"
|
"ci-info": "1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-class": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz",
|
||||||
|
"integrity": "sha1-4FdFFwW7NOOePjNZjJOpg3KWtzY="
|
||||||
|
},
|
||||||
"is-data-descriptor": {
|
"is-data-descriptor": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
||||||
|
@ -8085,6 +8146,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
|
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"async-limiter": "1.0.0",
|
||||||
|
"safe-buffer": "5.1.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -8155,6 +8226,14 @@
|
||||||
"verror": "1.10.0"
|
"verror": "1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keypather": {
|
||||||
|
"version": "1.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/keypather/-/keypather-1.10.2.tgz",
|
||||||
|
"integrity": "sha1-4ESWMtSz5RbyHMAUznxWRP3c5hQ=",
|
||||||
|
"requires": {
|
||||||
|
"101": "1.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||||
|
@ -9046,6 +9125,15 @@
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mock-socket": {
|
||||||
|
"version": "8.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-8.0.4.tgz",
|
||||||
|
"integrity": "sha512-xuO+Ep0xI60sXfBwIXezHuBnSj3Rafh6TSeTH81k2aFuNf64JW46PeDaViWMXQ/nMInknUzfMriPkoVhmh5Aag==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"url-parse": "1.4.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"modify-values": {
|
"modify-values": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
|
||||||
|
@ -9055,8 +9143,7 @@
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"mute-stream": {
|
"mute-stream": {
|
||||||
"version": "0.0.7",
|
"version": "0.0.7",
|
||||||
|
@ -13001,6 +13088,12 @@
|
||||||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
|
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"querystringify": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"quick-lru": {
|
"quick-lru": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
|
||||||
|
@ -13376,6 +13469,12 @@
|
||||||
"resolve-from": "1.0.1"
|
"resolve-from": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"reselect": {
|
"reselect": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
|
||||||
|
@ -13690,6 +13789,39 @@
|
||||||
"minimatch": "3.0.4"
|
"minimatch": "3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rpc-websockets": {
|
||||||
|
"version": "4.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-4.3.3.tgz",
|
||||||
|
"integrity": "sha512-Pq+tubbPkY63e0b1jukKkEQNWa5twpSvdd5izvtAK8OAw4qGGbWzJytqOdtProzpZQhFzynaHLNwfocmx8tmbg==",
|
||||||
|
"requires": {
|
||||||
|
"assert-args": "1.2.1",
|
||||||
|
"babel-runtime": "6.26.0",
|
||||||
|
"circular-json": "0.5.9",
|
||||||
|
"eventemitter3": "3.1.0",
|
||||||
|
"uuid": "3.3.2",
|
||||||
|
"ws": "5.2.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"circular-json": {
|
||||||
|
"version": "0.5.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
|
||||||
|
"integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ=="
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "5.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||||
|
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||||
|
"requires": {
|
||||||
|
"async-limiter": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"rst-selector-parser": {
|
"rst-selector-parser": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
|
||||||
|
@ -15511,6 +15643,11 @@
|
||||||
"prelude-ls": "1.1.2"
|
"prelude-ls": "1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"type-detect": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
|
||||||
|
"integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI="
|
||||||
|
},
|
||||||
"typedarray": {
|
"typedarray": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
@ -15758,6 +15895,16 @@
|
||||||
"integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=",
|
"integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"url-parse": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"querystringify": "2.1.0",
|
||||||
|
"requires-port": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"url-parse-lax": {
|
"url-parse-lax": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
|
||||||
|
@ -16041,13 +16188,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "4.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz",
|
||||||
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
|
"integrity": "sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "1.0.0",
|
"async-limiter": "1.0.0"
|
||||||
"safe-buffer": "5.1.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"xml-name-validator": {
|
"xml-name-validator": {
|
||||||
|
|
|
@ -59,8 +59,10 @@
|
||||||
"jayson": "^2.0.6",
|
"jayson": "^2.0.6",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
"node-fetch": "^2.2.0",
|
"node-fetch": "^2.2.0",
|
||||||
|
"rpc-websockets": "^4.3.3",
|
||||||
"superstruct": "^0.6.0",
|
"superstruct": "^0.6.0",
|
||||||
"tweetnacl": "^1.0.0"
|
"tweetnacl": "^1.0.0",
|
||||||
|
"ws": "^6.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "6.26.3",
|
"babel-core": "6.26.3",
|
||||||
|
|
|
@ -70,18 +70,31 @@ function generateConfig(configType) {
|
||||||
// maintained.
|
// maintained.
|
||||||
config.external = [
|
config.external = [
|
||||||
'assert',
|
'assert',
|
||||||
|
'babel-runtime/core-js/get-iterator',
|
||||||
|
'babel-runtime/core-js/json/stringify',
|
||||||
|
'babel-runtime/core-js/object/assign',
|
||||||
|
'babel-runtime/core-js/object/get-prototype-of',
|
||||||
|
'babel-runtime/core-js/object/keys',
|
||||||
'babel-runtime/core-js/promise',
|
'babel-runtime/core-js/promise',
|
||||||
'babel-runtime/helpers/asyncToGenerator',
|
'babel-runtime/helpers/asyncToGenerator',
|
||||||
'babel-runtime/helpers/classCallCheck',
|
'babel-runtime/helpers/classCallCheck',
|
||||||
'babel-runtime/helpers/createClass',
|
'babel-runtime/helpers/createClass',
|
||||||
|
'babel-runtime/helpers/get',
|
||||||
|
'babel-runtime/helpers/inherits',
|
||||||
|
'babel-runtime/helpers/possibleConstructorReturn',
|
||||||
'babel-runtime/helpers/toConsumableArray',
|
'babel-runtime/helpers/toConsumableArray',
|
||||||
'babel-runtime/helpers/typeof',
|
'babel-runtime/helpers/typeof',
|
||||||
'babel-runtime/regenerator',
|
'babel-runtime/regenerator',
|
||||||
|
'bn.js',
|
||||||
'bs58',
|
'bs58',
|
||||||
|
'buffer-layout',
|
||||||
|
'elfy',
|
||||||
'jayson/lib/client/browser',
|
'jayson/lib/client/browser',
|
||||||
'node-fetch',
|
'node-fetch',
|
||||||
|
'rpc-websockets',
|
||||||
'superstruct',
|
'superstruct',
|
||||||
'tweetnacl',
|
'tweetnacl',
|
||||||
|
'url',
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
import {
|
||||||
|
parse as urlParse,
|
||||||
|
format as urlFormat,
|
||||||
|
} from 'url';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import jayson from 'jayson/lib/client/browser';
|
import jayson from 'jayson/lib/client/browser';
|
||||||
import {struct} from 'superstruct';
|
import {struct} from 'superstruct';
|
||||||
|
import {Client as RpcWebSocketClient} from 'rpc-websockets';
|
||||||
|
|
||||||
import {Transaction} from './transaction';
|
import {Transaction} from './transaction';
|
||||||
import {PublicKey} from './publickey';
|
import {PublicKey} from './publickey';
|
||||||
|
@ -11,6 +16,7 @@ import {sleep} from './util/sleep';
|
||||||
import type {Account} from './account';
|
import type {Account} from './account';
|
||||||
import type {TransactionSignature, TransactionId} from './transaction';
|
import type {TransactionSignature, TransactionId} from './transaction';
|
||||||
|
|
||||||
|
|
||||||
type RpcRequest = (methodName: string, args: Array<any>) => any;
|
type RpcRequest = (methodName: string, args: Array<any>) => any;
|
||||||
|
|
||||||
function createRpcRequest(url): RpcRequest {
|
function createRpcRequest(url): RpcRequest {
|
||||||
|
@ -79,11 +85,10 @@ function jsonRpcResult(resultDescription: any) {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "getAccountInfo" message
|
* @private
|
||||||
*/
|
*/
|
||||||
const GetAccountInfoRpcResult = jsonRpcResult({
|
const AccountInfoResult = struct({
|
||||||
executable: 'boolean',
|
executable: 'boolean',
|
||||||
loader_program_id: 'array',
|
loader_program_id: 'array',
|
||||||
program_id: 'array',
|
program_id: 'array',
|
||||||
|
@ -91,6 +96,18 @@ const GetAccountInfoRpcResult = jsonRpcResult({
|
||||||
userdata: 'array',
|
userdata: 'array',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected JSON RPC response for the "getAccountInfo" message
|
||||||
|
*/
|
||||||
|
const GetAccountInfoRpcResult = jsonRpcResult(AccountInfoResult);
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Expected JSON RPC response for the "accountNotification" message
|
||||||
|
*/
|
||||||
|
const AccountNotificationResult = struct({
|
||||||
|
subscription: 'number',
|
||||||
|
result: AccountInfoResult,
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "confirmTransaction" message
|
* Expected JSON RPC response for the "confirmTransaction" message
|
||||||
|
@ -148,6 +165,20 @@ type AccountInfo = {
|
||||||
userdata: Buffer,
|
userdata: Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for account change notifications
|
||||||
|
*/
|
||||||
|
export type AccountChangeCallback = (accountInfo: AccountInfo) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
type AccountSubscriptionInfo = {
|
||||||
|
publicKey: string; // PublicKey of the account as a base 58 string
|
||||||
|
callback: AccountChangeCallback,
|
||||||
|
subscriptionId: null | number; // null when there's no current server subscription id
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Possible signature status values
|
* Possible signature status values
|
||||||
*
|
*
|
||||||
|
@ -164,6 +195,8 @@ export type SignatureStatus = 'Confirmed'
|
||||||
*/
|
*/
|
||||||
export class Connection {
|
export class Connection {
|
||||||
_rpcRequest: RpcRequest;
|
_rpcRequest: RpcRequest;
|
||||||
|
_rpcWebSocket: RpcWebSocketClient;
|
||||||
|
_rpcWebSocketConnected: boolean = false;
|
||||||
|
|
||||||
_lastIdInfo: {
|
_lastIdInfo: {
|
||||||
lastId: TransactionId | null,
|
lastId: TransactionId | null,
|
||||||
|
@ -171,6 +204,8 @@ export class Connection {
|
||||||
transactionSignatures: Array<string>,
|
transactionSignatures: Array<string>,
|
||||||
};
|
};
|
||||||
_disableLastIdCaching: boolean = false
|
_disableLastIdCaching: boolean = false
|
||||||
|
_accountChangeSubscriptions: {[number]: AccountSubscriptionInfo} = {};
|
||||||
|
_accountChangeSubscriptionCounter: number = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establish a JSON RPC connection
|
* Establish a JSON RPC connection
|
||||||
|
@ -178,15 +213,29 @@ export class Connection {
|
||||||
* @param endpoint URL to the fullnode JSON RPC endpoint
|
* @param endpoint URL to the fullnode JSON RPC endpoint
|
||||||
*/
|
*/
|
||||||
constructor(endpoint: string) {
|
constructor(endpoint: string) {
|
||||||
if (typeof endpoint !== 'string') {
|
let url = urlParse(endpoint);
|
||||||
throw new Error('Connection endpoint not specified');
|
|
||||||
}
|
this._rpcRequest = createRpcRequest(url.href);
|
||||||
this._rpcRequest = createRpcRequest(endpoint);
|
|
||||||
this._lastIdInfo = {
|
this._lastIdInfo = {
|
||||||
lastId: null,
|
lastId: null,
|
||||||
seconds: -1,
|
seconds: -1,
|
||||||
transactionSignatures: [],
|
transactionSignatures: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
url.protocol = 'ws';
|
||||||
|
url.host = '';
|
||||||
|
url.port = String(Number(url.port) + 1);
|
||||||
|
this._rpcWebSocket = new RpcWebSocketClient(
|
||||||
|
urlFormat(url),
|
||||||
|
{
|
||||||
|
autoconnect: false,
|
||||||
|
max_reconnects: Infinity,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this._rpcWebSocket.on('open', this._wsOnOpen.bind(this));
|
||||||
|
this._rpcWebSocket.on('error', this._wsOnError.bind(this));
|
||||||
|
this._rpcWebSocket.on('close', this._wsOnClose.bind(this));
|
||||||
|
this._rpcWebSocket.on('accountNotification', this._wsOnAccountNotification.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -371,4 +420,133 @@ export class Connection {
|
||||||
assert(res.result);
|
assert(res.result);
|
||||||
return res.result;
|
return res.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_wsOnOpen() {
|
||||||
|
this._rpcWebSocketConnected = true;
|
||||||
|
this._updateSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_wsOnError(err: Error) {
|
||||||
|
console.log('ws error:', err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_wsOnClose(code: number, message: string) {
|
||||||
|
// 1000 means _rpcWebSocket.close() was called explicitly
|
||||||
|
if (code !== 1000) {
|
||||||
|
console.log('ws close:', code, message);
|
||||||
|
}
|
||||||
|
this._rpcWebSocketConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_wsOnAccountNotification(notification: Object) {
|
||||||
|
const res = AccountNotificationResult(notification);
|
||||||
|
if (res.error) {
|
||||||
|
throw new Error(res.error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = Object.keys(this._accountChangeSubscriptions).map(Number);
|
||||||
|
for (let id of keys) {
|
||||||
|
const sub = this._accountChangeSubscriptions[id];
|
||||||
|
if (sub.subscriptionId === res.subscription) {
|
||||||
|
const {result} = res;
|
||||||
|
assert(typeof result !== 'undefined');
|
||||||
|
|
||||||
|
sub.callback({
|
||||||
|
executable: result.executable,
|
||||||
|
tokens: result.tokens,
|
||||||
|
programId: new PublicKey(result.program_id),
|
||||||
|
loaderProgramId: new PublicKey(result.loader_program_id),
|
||||||
|
userdata: Buffer.from(result.userdata),
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
async _updateSubscriptions() {
|
||||||
|
const keys = Object.keys(this._accountChangeSubscriptions).map(Number);
|
||||||
|
if (keys.length === 0) {
|
||||||
|
this._rpcWebSocket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._rpcWebSocketConnected) {
|
||||||
|
for (let id of keys) {
|
||||||
|
this._accountChangeSubscriptions[id].subscriptionId = null;
|
||||||
|
}
|
||||||
|
this._rpcWebSocket.connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let id of keys) {
|
||||||
|
const {subscriptionId, publicKey} = this._accountChangeSubscriptions[id];
|
||||||
|
if (subscriptionId === null) {
|
||||||
|
try {
|
||||||
|
this._accountChangeSubscriptions[id].subscriptionId =
|
||||||
|
await this._rpcWebSocket.call(
|
||||||
|
'accountSubscribe',
|
||||||
|
[publicKey]
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`accountSubscribe error for ${publicKey}: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback to be invoked whenever the specified account changes
|
||||||
|
*
|
||||||
|
* @param publickey Public key of the account to monitor
|
||||||
|
* @param callback Function to invoke whenever the account is changed
|
||||||
|
* @return subscription id
|
||||||
|
*/
|
||||||
|
onAccountChange(publicKey: PublicKey, callback: AccountChangeCallback): number {
|
||||||
|
const id = ++this._accountChangeSubscriptionCounter;
|
||||||
|
this._accountChangeSubscriptions[id] = {
|
||||||
|
publicKey: publicKey.toBase58(),
|
||||||
|
callback,
|
||||||
|
subscriptionId: null
|
||||||
|
};
|
||||||
|
this._updateSubscriptions();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deregister an account notification callback
|
||||||
|
*
|
||||||
|
* @param id subscription id to deregister
|
||||||
|
*/
|
||||||
|
async removeAccountChangeListener(id: number): Promise<void> {
|
||||||
|
if (this._accountChangeSubscriptions[id]) {
|
||||||
|
const {subscriptionId} = this._accountChangeSubscriptions[id];
|
||||||
|
delete this._accountChangeSubscriptions[id];
|
||||||
|
if (subscriptionId !== null) {
|
||||||
|
try {
|
||||||
|
await this._rpcWebSocket.call('accountUnsubscribe', [subscriptionId]);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('accountUnsubscribe error:', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._updateSubscriptions();
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown account change id: ${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,17 @@ export const mockRpc: Array<[string, RpcRequest, RpcResponse]> = [];
|
||||||
// identified by `url` instead of using the mock
|
// identified by `url` instead of using the mock
|
||||||
export const mockRpcEnabled = !process.env.DOITLIVE;
|
export const mockRpcEnabled = !process.env.DOITLIVE;
|
||||||
|
|
||||||
|
let mockNotice = true;
|
||||||
|
|
||||||
// Suppress lint: 'JestMockFn' is not defined
|
// Suppress lint: 'JestMockFn' is not defined
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const mock: JestMockFn<any, any> = jest.fn(
|
const mock: JestMockFn<any, any> = jest.fn(
|
||||||
(fetchUrl, fetchOptions) => {
|
(fetchUrl, fetchOptions) => {
|
||||||
if (!mockRpcEnabled) {
|
if (!mockRpcEnabled) {
|
||||||
console.log(`Note: node-fetch mock is disabled, testing live against ${fetchUrl}`);
|
if (mockNotice) {
|
||||||
|
console.log(`Note: node-fetch mock is disabled, testing live against ${fetchUrl}`);
|
||||||
|
mockNotice = false;
|
||||||
|
}
|
||||||
return fetch(fetchUrl, fetchOptions);
|
return fetch(fetchUrl, fetchOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import {Client as RpcWebSocketClient} from 'rpc-websockets';
|
||||||
|
|
||||||
|
// Define DOITLIVE in the environment to test against the real full node
|
||||||
|
// identified by `url` instead of using the mock
|
||||||
|
export const mockRpcEnabled = !process.env.DOITLIVE;
|
||||||
|
|
||||||
|
let mockNotice = true;
|
||||||
|
|
||||||
|
export class Client {
|
||||||
|
client: RpcWebSocketClient;
|
||||||
|
|
||||||
|
constructor(url, options) {
|
||||||
|
//console.log('MockClient', url, options);
|
||||||
|
if (!mockRpcEnabled) {
|
||||||
|
if (mockNotice) {
|
||||||
|
console.log('Note: rpc-websockets mock is disabled, testing live against', url);
|
||||||
|
mockNotice = false;
|
||||||
|
}
|
||||||
|
this.client = new RpcWebSocketClient(url, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (!mockRpcEnabled) {
|
||||||
|
return this.client.connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
if (!mockRpcEnabled) {
|
||||||
|
return this.client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on(event: string, callback: Function) {
|
||||||
|
if (!mockRpcEnabled) {
|
||||||
|
return this.client.on(event, callback);
|
||||||
|
}
|
||||||
|
//console.log('on', event);
|
||||||
|
}
|
||||||
|
|
||||||
|
async call(method: string, params: Object): Promise<Object> {
|
||||||
|
if (!mockRpcEnabled) {
|
||||||
|
return await this.client.call(method, params);
|
||||||
|
}
|
||||||
|
throw new Error('call unsupported');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Account,
|
Account,
|
||||||
Connection,
|
Connection,
|
||||||
|
BpfLoader,
|
||||||
|
Loader,
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
|
sendAndConfirmTransaction,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
||||||
import {mockGetLastId} from './mockrpc/getlastid';
|
import {mockGetLastId} from './mockrpc/getlastid';
|
||||||
|
@ -410,3 +412,46 @@ test('multi-instruction transaction', async () => {
|
||||||
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
|
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('account change notification', async () => {
|
||||||
|
if (mockRpcEnabled) {
|
||||||
|
console.log('non-live test skipped');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = new Connection(url);
|
||||||
|
const owner = new Account();
|
||||||
|
const programAccount = new Account();
|
||||||
|
|
||||||
|
const mockCallback = jest.fn();
|
||||||
|
|
||||||
|
const subscriptionId = connection.onAccountChange(programAccount.publicKey, mockCallback);
|
||||||
|
|
||||||
|
await connection.requestAirdrop(owner.publicKey, 42);
|
||||||
|
const transaction = SystemProgram.createAccount(
|
||||||
|
owner.publicKey,
|
||||||
|
programAccount.publicKey,
|
||||||
|
42,
|
||||||
|
3,
|
||||||
|
BpfLoader.programId,
|
||||||
|
);
|
||||||
|
await sendAndConfirmTransaction(connection, owner, transaction);
|
||||||
|
|
||||||
|
const loader = new Loader(connection, BpfLoader.programId);
|
||||||
|
await loader.load(programAccount, [1, 2, 3]);
|
||||||
|
|
||||||
|
await connection.removeAccountChangeListener(subscriptionId);
|
||||||
|
|
||||||
|
// mockCallback should be called twice
|
||||||
|
expect(mockCallback.mock.calls).toHaveLength(2);
|
||||||
|
|
||||||
|
// First mockCallback call is due to SystemProgram.createAccount()
|
||||||
|
expect(mockCallback.mock.calls[0][0].tokens).toBe(42);
|
||||||
|
expect(mockCallback.mock.calls[0][0].executable).toBe(false);
|
||||||
|
expect(mockCallback.mock.calls[0][0].userdata).toEqual(Buffer.from([0, 0, 0]));
|
||||||
|
expect(mockCallback.mock.calls[0][0].programId).toEqual(BpfLoader.programId);
|
||||||
|
|
||||||
|
// Second mockCallback call is due to loader.load()
|
||||||
|
expect(mockCallback.mock.calls[1][0].userdata).toEqual(Buffer.from([1, 2, 3]));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
/**
|
/**
|
||||||
* The connection url to use when running unit tests against a live network
|
* The connection url to use when running unit tests against a live network
|
||||||
*/
|
*/
|
||||||
export const url = 'http://localhost:8899';
|
export const url = 'http://localhost:8899/';
|
||||||
//export const url = 'http://testnet.solana.com:8899';
|
//export const url = 'http://testnet.solana.com:8899/';
|
||||||
//export const url = 'http://master.testnet.solana.com:8899';
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue