Skip to content

Commit

Permalink
feat!: change rpc methods signature to support fetch options
Browse files Browse the repository at this point in the history
Signal are now supported
  • Loading branch information
hugomrdias committed Sep 5, 2023
1 parent 0a0da99 commit e1908f9
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 108 deletions.
3 changes: 2 additions & 1 deletion packages/iso-filecoin/package.json
Expand Up @@ -99,6 +99,7 @@
"@scure/bip39": "^1.2.1",
"bignumber.js": "^9.1.1",
"iso-base": "workspace:^",
"iso-web": "workspace:^",
"zod": "^3.21.4"
},
"devDependencies": {
Expand All @@ -108,7 +109,7 @@
"assert": "^2.0.0",
"hd-scripts": "^7.0.0",
"mocha": "^10.2.0",
"playwright-test": "^12.1.1",
"playwright-test": "^12.2.0",
"typescript": "5.1.6"
},
"publishConfig": {
Expand Down
2 changes: 1 addition & 1 deletion packages/iso-filecoin/src/message.js
Expand Up @@ -110,7 +110,7 @@ export class Message {
(this.gasLimit === 0 && this.gasFeeCap === '0') ||
this.gasPremium === '0'
) {
const gas = await rpc.gasEstimate(this)
const gas = await rpc.gasEstimate({ msg: this })

if (gas.error) {
throw new Error(gas.error.message)
Expand Down
157 changes: 108 additions & 49 deletions packages/iso-filecoin/src/rpc.js
Expand Up @@ -5,52 +5,74 @@ import { getNetworkPrefix } from './utils.js'
export class RPC {
/**
* @param {import("./types.js").Options} options
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
constructor({
api,
token,
network = 'mainnet',
fetch = globalThis.fetch.bind(globalThis),
}) {
constructor(
{
api,
token,
network = 'mainnet',
fetch = globalThis.fetch.bind(globalThis),
},
fetchOptions = {}
) {
this.fetch = fetch
this.api = new URL(api)
this.network = network
this.headers = {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
}

this.fetchOptions = fetchOptions
}

async version() {
return /** @type {import("./types.js").VersionResponse} */ (
await this.call('Filecoin.Version')
/**
* Version returns the version of the Filecoin node.
*
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async version(fetchOptions = {}) {
return /** @type {import('./types.js').VersionResponse} */ (
await this.call({ method: 'Filecoin.Version' }, fetchOptions)
)
}

async networkName() {
/**
* NetworkName returns the name of the network the node is synced to.
*
* @param {import('./types.js').FetchOptions} [fetchOptions]
* @returns
*/
async networkName(fetchOptions = {}) {
return /** @type {import("./types.js").StateNetworkNameResponse} */ (
await this.call('Filecoin.StateNetworkName')
await this.call({ method: 'Filecoin.StateNetworkName' }, fetchOptions)
)
}

/**
* GasEstimateMessageGas estimates gas values for unset message gas fields
*
* @see https://lotus.filecoin.io/reference/lotus/gas/#gasestimatemessagegas
* @param {import("./types.js").PartialMessageObj} msg
* @param {string} maxFee - max fee to pay for gas (attoFIL/gas units)
*
* @param {import('./types.js').GasEstimateParams} params
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async gasEstimate(msg, maxFee = '0') {
this.#validateNetwork(msg.from)
this.#validateNetwork(msg.to)
async gasEstimate(params, fetchOptions = {}) {
this.#validateNetwork(params.msg.from)
this.#validateNetwork(params.msg.to)

return /** @type {import("./types.js").GasEstimateMessageGasResponse} */ (
await this.call(
'Filecoin.GasEstimateMessageGas',
new Message(msg).toLotus(),
{ MaxFee: maxFee },
// eslint-disable-next-line unicorn/no-useless-undefined
undefined
{
method: 'Filecoin.GasEstimateMessageGas',
params: [
new Message(params.msg).toLotus(),
{ MaxFee: params.maxFee ?? '0' },
undefined,
],
},
fetchOptions
)
)
}
Expand All @@ -59,12 +81,17 @@ export class RPC {
* WalletBalance returns the balance of the given address at the current head of the chain.
*
* @see https://lotus.filecoin.io/reference/lotus/wallet/#walletbalance
*
* @param {string} address
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async balance(address) {
async balance(address, fetchOptions = {}) {
address = this.#validateNetwork(address)
return /** @type {import("./types.js").WalletBalanceResponse} */ (
await this.call('Filecoin.WalletBalance', address)
await this.call(
{ method: 'Filecoin.WalletBalance', params: [address] },
fetchOptions
)
)
}

Expand All @@ -73,48 +100,66 @@ export class RPC {
*
* @see https://lotus.filecoin.io/reference/lotus/mpool/#mpoolgetnonce
* @param {string} address
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async nonce(address) {
async nonce(address, fetchOptions = {}) {
address = this.#validateNetwork(address)
return /** @type {import("./types.js").MpoolGetNonceResponse} */ (
await this.call('Filecoin.MpoolGetNonce', address)
await this.call(
{ method: 'Filecoin.MpoolGetNonce', params: [address] },
fetchOptions
)
)
}

/**
* MpoolPush pushes a signed message to mempool.
*
* @see https://lotus.filecoin.io/reference/lotus/mpool/#mpoolpush
* @param {import('./types.js').MessageObj} msg
* @param {import('./types.js').SignatureObj} signature
*
* @param {import('./types.js').PushMessageParams} params
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async pushMessage(msg, signature) {
this.#validateNetwork(msg.from)
this.#validateNetwork(msg.to)
async pushMessage(params, fetchOptions = {}) {
this.#validateNetwork(params.msg.from)
this.#validateNetwork(params.msg.to)

return /** @type {import("./types.js").MpoolPushResponse} */ (
await this.call('Filecoin.MpoolPush', {
Message: new Message(msg).toLotus(),
Signature: new Signature(signature).toLotus(),
})
await this.call(
{
method: 'Filecoin.MpoolPush',
params: [
{
Message: new Message(params.msg).toLotus(),
Signature: new Signature(params.signature).toLotus(),
},
],
},
fetchOptions
)
)
}

/**
* StateWaitMsg looks back in the chain for a message. If not found, it blocks until the message arrives on chain, and gets to the indicated confidence depth.
*
* @param {{ "/": string }} cid
* @param {number} confidence
* @param {number} lookBackLimit
* @see https://lotus.filecoin.io/reference/lotus/state/#statewaitmsg
* @param {import('./types.js').waitMsgParams} params
* @param {import('./types.js').FetchOptions} [fetchOptions]
*/
async stateWaitMsg(cid, confidence = 2, lookBackLimit = 100) {
return /** @type {any} */ (
async waitMsg(params, fetchOptions = {}) {
return /** @type {import('./types.js').WaitMsgResponse} */ (
await this.call(
'Filecoin.StateWaitMsg',
cid,
confidence,
lookBackLimit,
false
{
method: 'Filecoin.StateWaitMsg',
params: [
params.cid,
params.confidence ?? 2,
params.lookback ?? 100,
false,
],
},
fetchOptions
)
)
}
Expand All @@ -123,20 +168,27 @@ export class RPC {
* Generic method to call any method on the lotus rpc api.
*
* @template R
* @param {string} method
* @param {any[]} params
* @param {import('./types.js').RpcOptions} rpcOptions
* @param {import('./types.js').FetchOptions} [fetchOptions]
* @returns {Promise<R | import('./types.js').RpcError>}
*/
async call(method, ...params) {

async call(rpcOptions, fetchOptions = {}) {
const opts = {
...this.fetchOptions,
...fetchOptions,
}
try {
const res = await this.fetch(this.api, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
jsonrpc: '2.0',
method,
params,
method: rpcOptions.method,
params: rpcOptions.params,
id: 1,
}),
signal: opts.signal ?? AbortSignal.timeout(opts.timeout ?? 5000),
})

if (res.ok) {
Expand Down Expand Up @@ -187,6 +239,13 @@ export class RPC {
},
})
}

return /** @type {import("./types.js").RpcError} */ ({
error: {
code: 0,
message: `ERROR: unknown error`,
},
})
}

/**
Expand Down

0 comments on commit e1908f9

Please sign in to comment.