-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(middleware): generate autorest wrapper
- Loading branch information
Showing
7 changed files
with
681 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// eslint-disable-next-line max-classes-per-file | ||
import BigNumber from 'bignumber.js'; | ||
import { OperationArguments, OperationSpec } from '@azure/core-client'; | ||
import { | ||
genRequestQueuesPolicy, genCombineGetRequestsPolicy, genErrorFormatterPolicy, | ||
genVersionCheckPolicy, genRetryOnFailurePolicy, | ||
} from './utils/autorest'; | ||
import { Middleware as MiddlewareApi, MiddlewareOptionalParams, ErrorResponse } from './apis/middleware'; | ||
import { mapObject } from './utils/other'; | ||
import { Encoded } from './utils/encoder'; | ||
import { ConsensusProtocolVersion } from './tx/builder/constants'; | ||
|
||
const bigIntPropertyNames = [] as const; | ||
|
||
const numberPropertyNames = [] as const; | ||
|
||
class MiddlewareTransformed extends MiddlewareApi { | ||
override async sendOperationRequest( | ||
operationArguments: OperationArguments, | ||
operationSpec: OperationSpec, | ||
): Promise<any> { | ||
const args = mapObject( | ||
operationArguments, | ||
([key, value]) => [key, this.#encodeArg(value)], | ||
) as OperationArguments; | ||
return this.#decodeRes(await super.sendOperationRequest(args, operationSpec)); | ||
} | ||
|
||
#mapData(data: any, transform: { | ||
bigInt: (v: any) => any; | ||
number: (v: any) => any; | ||
}): unknown { | ||
if (Array.isArray(data)) return data.map((d) => this.#mapData(d, transform)); | ||
if (data != null && typeof data === 'object') { | ||
return mapObject(data, ([key, value]) => { | ||
if (value == null) return [key, value]; | ||
if (bigIntPropertyNames.some((k) => k === key)) return [key, transform.bigInt(value)]; | ||
if (numberPropertyNames.some((k) => k === key)) return [key, transform.number(value)]; | ||
return [key, this.#mapData(value, transform)]; | ||
}); | ||
} | ||
return data; | ||
} | ||
|
||
#encodeArg(data: any): any { | ||
return this.#mapData(data, { | ||
bigInt: (value) => { | ||
if (value instanceof BigNumber) return value.toFixed(); | ||
return value.toString(); | ||
}, | ||
number: (value) => value.toString(), | ||
}); | ||
} | ||
|
||
#decodeRes(data: any): any { | ||
return this.#mapData(data, { | ||
bigInt: (value) => BigInt(value), | ||
number: (value) => +value, | ||
}); | ||
} | ||
} | ||
|
||
type BigIntPropertyNames = typeof bigIntPropertyNames[number]; | ||
type NumberPropertyNames = typeof numberPropertyNames[number]; | ||
type PreserveOptional<NewType, OrigType> = | ||
OrigType extends undefined ? NewType | undefined : NewType; | ||
export type TransformMiddlewareType<Type> = | ||
Type extends (...args: infer Args) => infer Ret | ||
? (...args: TransformMiddlewareType<Args>) => TransformMiddlewareType<Ret> | ||
: Type extends [infer Item, ...infer Rest] | ||
? [TransformMiddlewareType<Item>, ...TransformMiddlewareType<Rest>] | ||
: Type extends Array<infer Item> | ||
? Array<TransformMiddlewareType<Item>> | ||
: Type extends Promise<infer T> | ||
? Promise<TransformMiddlewareType<T>> | ||
: Type extends { [P in any]: any } | ||
? { | ||
[Property in keyof Type]: | ||
Property extends BigIntPropertyNames | ||
? PreserveOptional<bigint, Type[Property]> | ||
: Property extends NumberPropertyNames | ||
? PreserveOptional<number, Type[Property]> | ||
: Property extends 'txHash' | ||
? PreserveOptional<Encoded.TxHash, Type[Property]> | ||
: Property extends 'bytecode' | ||
? PreserveOptional<Encoded.ContractBytearray, Type[Property]> | ||
: TransformMiddlewareType<Type[Property]> | ||
} | ||
: Type; | ||
type MiddlewareTransformedApi = new (...args: ConstructorParameters<typeof MiddlewareApi>) => { | ||
[Name in keyof InstanceType<typeof MiddlewareApi>]: | ||
Name extends 'pipeline' | 'sendRequest' | 'sendOperationRequest' | ||
? MiddlewareApi[Name] : TransformMiddlewareType<MiddlewareApi[Name]> | ||
}; | ||
|
||
export interface MiddlewareInfo { | ||
url: string; | ||
nodeNetworkId: string; | ||
version: string; | ||
consensusProtocolVersion: ConsensusProtocolVersion; | ||
} | ||
|
||
export default class Middleware | ||
extends (MiddlewareTransformed as unknown as MiddlewareTransformedApi) { | ||
/** | ||
* @param url - Url for middleware API | ||
* @param options - Options | ||
* @param options.ignoreVersion - Don't check node version | ||
* @param options.retryCount - Amount of extra requests to do in case of failure | ||
* @param options.retryOverallDelay - Time in ms to wait between all retries | ||
*/ | ||
constructor( | ||
url: string, | ||
{ | ||
ignoreVersion = false, retryCount = 3, retryOverallDelay = 800, ...options | ||
}: MiddlewareOptionalParams & { | ||
ignoreVersion?: boolean; | ||
retryCount?: number; | ||
retryOverallDelay?: number; | ||
} = {}, | ||
) { | ||
// eslint-disable-next-line constructor-super | ||
super(url, { | ||
allowInsecureConnection: true, | ||
additionalPolicies: [ | ||
genRequestQueuesPolicy(), | ||
genCombineGetRequestsPolicy(), | ||
genRetryOnFailurePolicy(retryCount, retryOverallDelay), | ||
genErrorFormatterPolicy((body: ErrorResponse) => ` ${body.error}`), | ||
], | ||
...options, | ||
}); | ||
if (!ignoreVersion) { | ||
const statusPromise = this.getStatus(); | ||
const versionPromise = statusPromise.then(({ mdwVersion }) => mdwVersion, (error) => error); | ||
this.pipeline.addPolicy( | ||
genVersionCheckPolicy('middleware', '/v2/status', versionPromise, '1.47.0', '2.0.0'), | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { describe, it } from 'mocha'; | ||
import { expect } from 'chai'; | ||
import '../index'; | ||
import { _Middleware } from '../../src'; | ||
|
||
describe('MiddlewareSubscriber', () => { | ||
// TODO: remove after solving https://github.com/aeternity/ae_mdw/issues/1336 | ||
const middleware = new _Middleware('https://testnet.aeternity.io/mdw/'); | ||
|
||
it('gets status', async () => { | ||
const res = await middleware.getStatus(); | ||
const expectedRes: typeof res = { | ||
mdwAsyncTasks: { | ||
longTasks: 0, | ||
producerBuffer: 0, | ||
totalPending: res.mdwAsyncTasks.totalPending, | ||
}, | ||
mdwGensPerMinute: res.mdwGensPerMinute, | ||
mdwHeight: res.mdwHeight, | ||
mdwLastMigration: 20230519120000, | ||
mdwRevision: '2d3ae3d', | ||
mdwSynced: true, | ||
mdwSyncing: true, | ||
mdwTxIndex: res.mdwTxIndex, | ||
mdwVersion: '1.49.0', | ||
nodeHeight: res.nodeHeight, | ||
nodeProgress: 100, | ||
nodeRevision: 'a42c1b1e84dabdad350005213a2a9334113a6832', | ||
nodeSyncing: false, | ||
nodeVersion: '6.8.1', | ||
}; | ||
expect(res).to.be.eql(expectedRes); | ||
}); | ||
|
||
it('gets account activities', async () => { | ||
const res = await middleware.getAccountActivities('ak_DtJrupsqqByQag76NrxAAimmkYJMk7on7z3xktdZpdkmxKQak'); | ||
const expectedRes: typeof res = { | ||
data: [{ | ||
blockHash: 'mh_LAo6Cg6d8LGDpxJ3se2aGJZbCubDZyC6GonHK58MKiW4a4LWb', | ||
height: 779178, | ||
payload: { | ||
block_hash: 'mh_LAo6Cg6d8LGDpxJ3se2aGJZbCubDZyC6GonHK58MKiW4a4LWb', | ||
block_height: 779178, | ||
hash: 'th_YHj5aB6JzHciY5f6jqgtso8u2iY9p6MT9RV96FwXQNS1MpSML', | ||
micro_index: 18, | ||
micro_time: 1684995426848, | ||
tx: { | ||
abi_version: 3, | ||
auth_data: 'cb_KxFs8lcLOwKfAKC2+ARNbHQ/i2cN0jPpYmw2o6/mve+skTCovW+5OcIa4p8BAQBRsNynuucudvyocC+ZWBzpUbjiGWctldfdDOR9csCIDeXwMpQ3yyJlC91g8AuFAB2uhHMjHNz5fGqWhxbju/QDsvQe5g==', | ||
fee: 78540000000000, | ||
ga_id: 'ak_DtJrupsqqByQag76NrxAAimmkYJMk7on7z3xktdZpdkmxKQak', | ||
gas: 50000, | ||
gas_price: 1000000000, | ||
gas_used: 8444, | ||
return_type: 'ok', | ||
tx: { | ||
signatures: [], | ||
tx: { | ||
amount: 112, | ||
fee: 16660000000000, | ||
nonce: 0, | ||
payload: 'ba_Xfbg4g==', | ||
recipient_id: 'ak_VTNurrhRhJBVK19JfUnEv4qgdZJT7DUghxz3ACEFBNKgw8R3D', | ||
sender_id: 'ak_DtJrupsqqByQag76NrxAAimmkYJMk7on7z3xktdZpdkmxKQak', | ||
type: 'SpendTx', | ||
version: 1, | ||
}, | ||
}, | ||
type: 'GAMetaTx', | ||
version: 2, | ||
}, | ||
}, | ||
type: 'GAMetaTxEvent', | ||
}, { | ||
blockHash: 'mh_2R1PVwTNP3Jha7oRby9Me3SRBP4R9he6RMH6eCCJGyVBHAzy5f', | ||
height: 779178, | ||
payload: { | ||
block_hash: 'mh_2R1PVwTNP3Jha7oRby9Me3SRBP4R9he6RMH6eCCJGyVBHAzy5f', | ||
block_height: 779178, | ||
hash: 'th_AScnu6AAGHvfewMELKvmc6KH9jaMfzopGpcFFo1HAoS7ne1fD', | ||
micro_index: 11, | ||
micro_time: 1684995366595, | ||
signatures: [ | ||
'sg_SBD5RkjMkfDM8KGJTgTTgmfXaimac2cGy4x39efXZjrPdr5zVJAmqu8dLiMNoVX1FHTESERRvejAnDVDjxLq6x2gb1SzK', | ||
], | ||
tx: { | ||
abi_version: 3, | ||
args: [ | ||
{ | ||
type: 'address', | ||
value: 'ak_2PahBfbkrmBFfbb4FGEVErP7mChFGPYFb9eGMARU514u5V3K52', | ||
}, | ||
], | ||
auth_fun: '0x6cf2570b0a1599b708291e50aa3daf13d0c7f2484bc337ddad2413a37fd4a009', | ||
auth_fun_name: 'authorize', | ||
call_data: 'cb_KxFE1kQfG58AoLb4BE1sdD+LZw3SM+libDajr+a976yRMKi9b7k5whrijU9L2Q==', | ||
code: 'cb_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', | ||
contract_id: 'ct_2TRQYcmvhRrbGrNKXy8uBZX2MQbgHrZmVCEHZBAJkhs24DdeVP', | ||
fee: 107820000000000, | ||
gas: 597, | ||
gas_price: 1000000000, | ||
gas_used: 478, | ||
nonce: 1, | ||
owner_id: 'ak_DtJrupsqqByQag76NrxAAimmkYJMk7on7z3xktdZpdkmxKQak', | ||
return_type: 'ok', | ||
type: 'GAAttachTx', | ||
version: 1, | ||
vm_version: 7, | ||
}, | ||
}, | ||
type: 'GAAttachTxEvent', | ||
}, { | ||
blockHash: 'mh_25snWYwTkU1xjPCcH592XVNzL894qSpF4yqnt8tABKGEVm6nSz', | ||
height: 779178, | ||
payload: { | ||
block_hash: 'mh_25snWYwTkU1xjPCcH592XVNzL894qSpF4yqnt8tABKGEVm6nSz', | ||
block_height: 779178, | ||
hash: 'th_242zV1qXwag6iBH3Pd8zn3DQC37h4uP38CoFjkaTgT19AVKMHo', | ||
micro_index: 7, | ||
micro_time: 1684995336526, | ||
signatures: [ | ||
'sg_E1Ezn9EMsxTZz7a93Zc5kjXkS1t3WqFbr3X8DqqjdXXfXD9Xy6DZQpjB2rHfcoZ3ySZ1FHh9bzMjfQfdA9mRJJ4yeYdfN', | ||
], | ||
tx: { | ||
amount: 5000000000000000000, | ||
fee: 17040000000000, | ||
nonce: 37016, | ||
payload: 'ba_RmF1Y2V0IFR4tYtyuw==', | ||
recipient_id: 'ak_DtJrupsqqByQag76NrxAAimmkYJMk7on7z3xktdZpdkmxKQak', | ||
sender_id: 'ak_2iBPH7HUz3cSDVEUWiHg76MZJ6tZooVNBmmxcgVK6VV8KAE688', | ||
type: 'SpendTx', | ||
version: 1, | ||
}, | ||
}, | ||
type: 'SpendTxEvent', | ||
}], | ||
next: null, | ||
prev: null, | ||
}; | ||
expect(res).to.be.eql(expectedRes); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { spawnSync } from 'child_process'; | ||
|
||
const run = (getOutput, command, ...args) => { | ||
const { error, stdout } = spawnSync( | ||
command, | ||
args, | ||
{ shell: true, ...!getOutput && { stdio: 'inherit' } }, | ||
); | ||
if (error) throw error; | ||
return stdout?.toString().trim(); | ||
}; | ||
|
||
const id = run(true, 'docker', 'create', 'aeternity/ae_mdw:1.47.0'); | ||
const openapi = '/home/aeternity/node/lib/ae_mdw-1.47.0/priv/static/swagger/swagger_v2.yaml'; | ||
run(false, 'docker', 'cp', `${id}:${openapi}`, './tooling/autorest/middleware-openapi.yaml'); | ||
run(false, 'docker', 'rm', '-v', id); |
Oops, something went wrong.