feat: wasm contracts intergration
This commit is contained in:
committed by
Piotr Pędziwiatr
parent
47fb5b1c59
commit
4e38dec7f9
@@ -51,6 +51,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/redstone-finance/redstone-smartweave#readme",
|
||||
"dependencies": {
|
||||
"@assemblyscript/loader": "^0.19.23",
|
||||
"@weavery/clarity": "^0.1.5",
|
||||
"arweave": "^1.10.16",
|
||||
"arweave-multihost": "^0.1.0",
|
||||
|
||||
@@ -36,6 +36,7 @@ describe('Testing the SmartWeave client for WASM contract', () => {
|
||||
});
|
||||
|
||||
LoggerFactory.INST.logLevel('error');
|
||||
LoggerFactory.INST.logLevel('debug', 'WasmContractHandlerApi');
|
||||
|
||||
smartweave = SmartWeaveNodeFactory.memCached(arweave);
|
||||
|
||||
@@ -62,35 +63,29 @@ describe('Testing the SmartWeave client for WASM contract', () => {
|
||||
await arlocal.stop();
|
||||
});
|
||||
|
||||
it('should properly deploy contract with initial state', async () => {
|
||||
it('should properly deploy contract', async () => {
|
||||
const contractTx = await arweave.transactions.get(contractTxId);
|
||||
|
||||
expect(contractTx).not.toBeNull();
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
it('should properly add new interaction', async () => {
|
||||
await contract.writeInteraction({ function: 'add' });
|
||||
|
||||
await mineBlock(arweave);
|
||||
|
||||
expect((await contract.readState()).state.counter).toEqual(556);
|
||||
it('should properly read initial state', async () => {
|
||||
expect((await contract.readState()).state.counter).toEqual(0);
|
||||
});
|
||||
|
||||
it('should properly add another interactions', async () => {
|
||||
await contract.writeInteraction({ function: 'add' });
|
||||
it('should properly read state after adding interactions', async () => {
|
||||
await contract.writeInteraction({ function: 'increment' });
|
||||
await mineBlock(arweave);
|
||||
await contract.writeInteraction({ function: 'add' });
|
||||
await contract.writeInteraction({ function: 'increment' });
|
||||
await mineBlock(arweave);
|
||||
await contract.writeInteraction({ function: 'add' });
|
||||
await contract.writeInteraction({ function: 'increment' });
|
||||
await mineBlock(arweave);
|
||||
|
||||
expect((await contract.readState()).state.counter).toEqual(559);
|
||||
expect((await contract.readState()).state.counter).toEqual(3);
|
||||
});
|
||||
|
||||
it('should properly view contract state', async () => {
|
||||
const interactionResult = await contract.viewState<unknown, number>({ function: 'value' });
|
||||
expect(interactionResult.result).toEqual(559);
|
||||
});*/
|
||||
const interactionResult = await contract.viewState<unknown, any>({ function: 'fullName' });
|
||||
|
||||
expect(interactionResult.result.fullName).toEqual("first_ppe last_ppe");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/**
|
||||
* This type contains all data and meta-data of the given contact.
|
||||
*/
|
||||
import {ContractType} from "./modules/CreateContract";
|
||||
|
||||
export type ContractDefinition<State> = {
|
||||
txId: string;
|
||||
srcTxId: string;
|
||||
src: string;
|
||||
src: ArrayBuffer;
|
||||
initState: State;
|
||||
minFee: string;
|
||||
owner: string;
|
||||
contractType: ContractType;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
ArweaveWrapper,
|
||||
Benchmark,
|
||||
ContractDefinition,
|
||||
ContractType,
|
||||
DefinitionLoader,
|
||||
getTag,
|
||||
LoggerFactory,
|
||||
@@ -50,6 +51,10 @@ export class ContractDefinitionLoader implements DefinitionLoader {
|
||||
this.logger.debug('Tags decoding', benchmark.elapsed());
|
||||
benchmark.reset();
|
||||
|
||||
const contractSrcTx = await this.arweaveWrapper.tx(contractSrcTxId);
|
||||
const contractType: ContractType =
|
||||
getTag(contractSrcTx, SmartWeaveTags.CONTENT_TYPE) == 'application/javascript' ? 'js' : 'wasm';
|
||||
|
||||
const src = await this.arweaveWrapper.txData(contractSrcTxId);
|
||||
this.logger.debug('Contract src tx load', benchmark.elapsed());
|
||||
benchmark.reset();
|
||||
@@ -63,18 +68,19 @@ export class ContractDefinitionLoader implements DefinitionLoader {
|
||||
src,
|
||||
initState,
|
||||
minFee,
|
||||
owner
|
||||
owner,
|
||||
contractType
|
||||
};
|
||||
}
|
||||
|
||||
private async evalInitialState(contractTx: Transaction) {
|
||||
private async evalInitialState(contractTx: Transaction): Promise<string> {
|
||||
if (getTag(contractTx, SmartWeaveTags.INIT_STATE)) {
|
||||
return getTag(contractTx, SmartWeaveTags.INIT_STATE);
|
||||
} else if (getTag(contractTx, SmartWeaveTags.INIT_STATE_TX)) {
|
||||
const stateTX = getTag(contractTx, SmartWeaveTags.INIT_STATE_TX);
|
||||
return this.arweaveWrapper.txData(stateTX);
|
||||
return this.arweaveWrapper.txDataString(stateTX);
|
||||
} else {
|
||||
return this.arweaveWrapper.txData(contractTx.id);
|
||||
return this.arweaveWrapper.txDataString(contractTx.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,4 +219,8 @@ export class ContractHandlerApi<State> implements HandlerApi<State> {
|
||||
return result?.cachedValue.state;
|
||||
};
|
||||
}
|
||||
|
||||
initState(state: State): void {
|
||||
// nth to do in this impl...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
|
||||
let currentState = baseState.state;
|
||||
const validity = baseState.validity;
|
||||
|
||||
executionContext.handler.initState(currentState);
|
||||
|
||||
this.logger.info(
|
||||
`Evaluating state for ${contractDefinition.txId} [${missingInteractions.length} non-cached of ${sortedInteractions.length} all]`
|
||||
);
|
||||
|
||||
@@ -10,6 +10,134 @@ import {
|
||||
SmartWeaveGlobal
|
||||
} from '@smartweave';
|
||||
import { ContractHandlerApi } from './ContractHandlerApi';
|
||||
import loader from '@assemblyscript/loader/umd';
|
||||
import { imports } from './wasmImports';
|
||||
import { WasmContractHandlerApi } from './WasmContractHandlerApi';
|
||||
|
||||
/**
|
||||
* A factory that produces handlers that are compatible with the "current" style of
|
||||
* writing SW contracts (ie. using "handle" function).
|
||||
*/
|
||||
export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknown>> {
|
||||
private readonly logger = LoggerFactory.INST.create('HandlerExecutorFactory');
|
||||
|
||||
constructor(private readonly arweave: Arweave) {}
|
||||
|
||||
async create<State>(contractDefinition: ContractDefinition<State>): Promise<HandlerApi<State>> {
|
||||
const swGlobal = new SmartWeaveGlobal(this.arweave, {
|
||||
id: contractDefinition.txId,
|
||||
owner: contractDefinition.owner
|
||||
});
|
||||
|
||||
if (contractDefinition.contractType == 'js') {
|
||||
const normalizedSource = normalizeContractSource(this.arweave.utils.bufferToString(contractDefinition.src));
|
||||
|
||||
const contractFunction = new Function(normalizedSource);
|
||||
|
||||
return new ContractHandlerApi(swGlobal, contractFunction, contractDefinition);
|
||||
} else {
|
||||
let wasmExports;
|
||||
|
||||
const wasmModule = loader.instantiateSync(contractDefinition.src, {
|
||||
metering: {
|
||||
usegas: (gas) => {
|
||||
if (gas < 0) {
|
||||
return;
|
||||
}
|
||||
swGlobal.gasUsed += gas;
|
||||
if (swGlobal.gasUsed > swGlobal.gasLimit) {
|
||||
throw new Error(
|
||||
`[RE:OOG] Out of gas! Limit: ${formatGas(swGlobal.gasUsed)}, used: ${formatGas(swGlobal.gasLimit)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
console: {
|
||||
'console.log': function (msgPtr) {
|
||||
console.log(`Contract: ${wasmExports.__getString(msgPtr)}`);
|
||||
},
|
||||
'console.logO': function (msgPtr, objPtr) {
|
||||
console.log(`Contract: ${wasmExports.__getString(msgPtr)}`, JSON.parse(wasmExports.__getString(objPtr)));
|
||||
}
|
||||
},
|
||||
block: {
|
||||
'Block.height': function () {
|
||||
return 875290;
|
||||
},
|
||||
'Block.indep_hash': function () {
|
||||
return wasmExports.__newString('iIMsQJ1819NtkEUEMBRl6-7I6xkeDipn1tK4w_cDFczRuD91oAZx5qlgSDcqq1J1');
|
||||
},
|
||||
'Block.timestamp': function () {
|
||||
return 123123123;
|
||||
}
|
||||
},
|
||||
transaction: {
|
||||
'Transaction.id': function () {
|
||||
return wasmExports.__newString('Transaction.id');
|
||||
},
|
||||
'Transaction.owner': function () {
|
||||
return wasmExports.__newString('Transaction.owner');
|
||||
},
|
||||
'Transaction.target': function () {
|
||||
return wasmExports.__newString('Transaction.target');
|
||||
}
|
||||
},
|
||||
contract: {
|
||||
'Contract.id': function () {
|
||||
return wasmExports.__newString('Contract.id');
|
||||
},
|
||||
'Contract.owner': function () {
|
||||
return wasmExports.__newString('Contract.owner');
|
||||
}
|
||||
},
|
||||
msg: {
|
||||
'msg.sender': function () {
|
||||
return wasmExports.__newString('msg.sender');
|
||||
}
|
||||
},
|
||||
api: {
|
||||
_readContractState: (fnIndex, contractTxIdPtr) => {
|
||||
const contractTxId = wasmExports.__getString(contractTxIdPtr);
|
||||
const callbackFn = getFn(fnIndex);
|
||||
console.log('Simulating read state of', contractTxId);
|
||||
return setTimeout(() => {
|
||||
console.log('calling callback');
|
||||
callbackFn(
|
||||
wasmExports.__newString(
|
||||
JSON.stringify({
|
||||
contractTxId
|
||||
})
|
||||
)
|
||||
);
|
||||
}, 1000);
|
||||
},
|
||||
clearTimeout
|
||||
},
|
||||
env: {
|
||||
abort(messagePtr, fileNamePtr, line, column) {
|
||||
console.error('--------------------- Error message from AssemblyScript ----------------------');
|
||||
console.error(' ' + wasmExports.__getString(messagePtr));
|
||||
console.error(' In file "' + wasmExports.__getString(fileNamePtr) + '"');
|
||||
console.error(` on line ${line}, column ${column}.`);
|
||||
console.error('------------------------------------------------------------------------------\n');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function getFn(idx) {
|
||||
return wasmExports.table.get(idx);
|
||||
}
|
||||
|
||||
function formatGas(gas) {
|
||||
return gas * 1e-4;
|
||||
}
|
||||
|
||||
wasmExports = wasmModule.exports;
|
||||
|
||||
return new WasmContractHandlerApi(swGlobal, contractDefinition, wasmExports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface InteractionData<Input> {
|
||||
interaction?: ContractInteraction<Input>;
|
||||
@@ -26,28 +154,8 @@ export interface HandlerApi<State> {
|
||||
currentResult: EvalStateResult<State>,
|
||||
interactionData: InteractionData<Input>
|
||||
): Promise<InteractionResult<State, Result>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory that produces handlers that are compatible with the "current" style of
|
||||
* writing SW contracts (ie. using "handle" function).
|
||||
*/
|
||||
export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknown>> {
|
||||
private readonly logger = LoggerFactory.INST.create('HandlerExecutorFactory');
|
||||
|
||||
constructor(private readonly arweave: Arweave) {}
|
||||
|
||||
async create<State>(contractDefinition: ContractDefinition<State>): Promise<HandlerApi<State>> {
|
||||
const normalizedSource = normalizeContractSource(contractDefinition.src);
|
||||
|
||||
const swGlobal = new SmartWeaveGlobal(this.arweave, {
|
||||
id: contractDefinition.txId,
|
||||
owner: contractDefinition.owner
|
||||
});
|
||||
const contractFunction = new Function(normalizedSource);
|
||||
|
||||
return new ContractHandlerApi(swGlobal, contractFunction, contractDefinition);
|
||||
}
|
||||
initState(state: State): void;
|
||||
}
|
||||
|
||||
export type HandlerFunction<State, Input, Result> = (
|
||||
|
||||
98
src/core/modules/impl/WasmContractHandlerApi.ts
Normal file
98
src/core/modules/impl/WasmContractHandlerApi.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/* eslint-disable */
|
||||
import {
|
||||
ContractDefinition,
|
||||
EvalStateResult,
|
||||
ExecutionContext,
|
||||
HandlerApi,
|
||||
InteractionData,
|
||||
InteractionResult,
|
||||
LoggerFactory,
|
||||
RedStoneLogger,
|
||||
SmartWeaveGlobal
|
||||
} from '@smartweave';
|
||||
import stringify from "safe-stable-stringify";
|
||||
|
||||
export class WasmContractHandlerApi<State> implements HandlerApi<State> {
|
||||
private readonly contractLogger: RedStoneLogger;
|
||||
private readonly logger = LoggerFactory.INST.create('WasmContractHandlerApi');
|
||||
|
||||
constructor(
|
||||
private readonly swGlobal: SmartWeaveGlobal,
|
||||
private readonly contractDefinition: ContractDefinition<State>,
|
||||
private readonly wasmExports: any
|
||||
) {
|
||||
this.contractLogger = LoggerFactory.INST.create(swGlobal.contract.id);
|
||||
}
|
||||
|
||||
initState(state: State): void {
|
||||
const statePtr = this.wasmExports.__newString(stringify(state));
|
||||
this.wasmExports.initState(statePtr);
|
||||
}
|
||||
|
||||
async handle<Input, Result>(
|
||||
executionContext: ExecutionContext<State>,
|
||||
currentResult: EvalStateResult<State>,
|
||||
interactionData: InteractionData<Input>
|
||||
): Promise<InteractionResult<State, Result>> {
|
||||
const contractLogger = LoggerFactory.INST.create('Contract');
|
||||
|
||||
|
||||
try {
|
||||
const {interaction, interactionTx, currentTx} = interactionData;
|
||||
|
||||
this.swGlobal._activeTx = interactionTx;
|
||||
|
||||
const handlerResult = this.doHandle(interaction);
|
||||
|
||||
return {
|
||||
type: 'ok',
|
||||
result: handlerResult,
|
||||
state: this.doGetCurrentState()
|
||||
};
|
||||
} catch (e) {
|
||||
// note: as exceptions handling in WASM is currently somewhat non-existent
|
||||
// https://www.assemblyscript.org/status.html#exceptions
|
||||
// and since we have to somehow differentiate different types of exceptions
|
||||
// - each exception message has to have a proper prefix added.
|
||||
|
||||
// exceptions with prefix [RE:] ("Runtime Exceptions") should break the execution immediately
|
||||
// - eg: [RE:OOG] - [RuntimeException: OutOfGas]
|
||||
|
||||
// exception with prefix [CE:] ("Contract Exceptions") should be logged, but should not break
|
||||
// the state evaluation - as they are considered as contracts' business exception (eg. validation errors)
|
||||
// - eg: [CE:WTF] - [ContractException: WhatTheFunction] ;-)
|
||||
if (e.message.startsWith('[RE:')) {
|
||||
return {
|
||||
type: 'exception',
|
||||
errorMessage: e.message,
|
||||
state: currentResult.state,
|
||||
result: null
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'error',
|
||||
errorMessage: e.message,
|
||||
state: currentResult.state,
|
||||
result: null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private doHandle(action: any): any {
|
||||
this.logger.info("Action", action.input);
|
||||
const actionPtr = this.wasmExports.__newString(stringify(action.input));
|
||||
const resultPtr = this.wasmExports.handle(actionPtr);
|
||||
const result = this.wasmExports.__getString(resultPtr);
|
||||
|
||||
this.logger.info("Result", result);
|
||||
this.logger.info("State", this.doGetCurrentState());
|
||||
|
||||
return JSON.parse(result);
|
||||
}
|
||||
|
||||
private doGetCurrentState(): State {
|
||||
const currentStatePtr = this.wasmExports.currentState();
|
||||
return JSON.parse(this.wasmExports.__getString(currentStatePtr));
|
||||
}
|
||||
}
|
||||
93
src/core/modules/impl/wasmImports.ts
Normal file
93
src/core/modules/impl/wasmImports.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import {SmartWeaveGlobal} from "@smartweave";
|
||||
|
||||
export function imports(swGlobal: SmartWeaveGlobal, wasmExports: any): any {
|
||||
return {
|
||||
metering: {
|
||||
usegas: (gas) => {
|
||||
if (gas < 0) {
|
||||
return;
|
||||
}
|
||||
swGlobal.gasUsed += gas;
|
||||
if (swGlobal.gasUsed > swGlobal.gasLimit) {
|
||||
throw new Error(`[RE:OOG] Out of gas! Limit: ${formatGas(swGlobal.gasUsed)}, used: ${formatGas(swGlobal.gasLimit)}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
console: {
|
||||
"console.log": function (msgPtr) {
|
||||
console.log(`Contract: ${wasmExports.__getString(msgPtr)}`);
|
||||
},
|
||||
"console.logO": function (msgPtr, objPtr) {
|
||||
console.log(`Contract: ${wasmExports.__getString(msgPtr)}`, JSON.parse(wasmExports.__getString(objPtr)));
|
||||
},
|
||||
},
|
||||
block: {
|
||||
"Block.height": function () {
|
||||
return 875290;
|
||||
},
|
||||
"Block.indep_hash": function () {
|
||||
return wasmExports.__newString("iIMsQJ1819NtkEUEMBRl6-7I6xkeDipn1tK4w_cDFczRuD91oAZx5qlgSDcqq1J1");
|
||||
},
|
||||
"Block.timestamp": function () {
|
||||
return 123123123;
|
||||
},
|
||||
},
|
||||
transaction: {
|
||||
"Transaction.id": function () {
|
||||
return wasmExports.__newString("Transaction.id");
|
||||
},
|
||||
"Transaction.owner": function () {
|
||||
return wasmExports.__newString("Transaction.owner");
|
||||
},
|
||||
"Transaction.target": function () {
|
||||
return wasmExports.__newString("Transaction.target");
|
||||
},
|
||||
},
|
||||
contract: {
|
||||
"Contract.id": function () {
|
||||
return wasmExports.__newString("Contract.id");
|
||||
},
|
||||
"Contract.owner": function () {
|
||||
return wasmExports.__newString("Contract.owner");
|
||||
},
|
||||
},
|
||||
msg: {
|
||||
"msg.sender": function () {
|
||||
return wasmExports.__newString("msg.sender");
|
||||
},
|
||||
},
|
||||
api: {
|
||||
_readContractState: (fnIndex, contractTxIdPtr) => {
|
||||
const contractTxId = wasmExports.__getString(contractTxIdPtr);
|
||||
const callbackFn = getFn(fnIndex);
|
||||
console.log("Simulating read state of", contractTxId);
|
||||
return setTimeout(() => {
|
||||
console.log('calling callback');
|
||||
callbackFn(wasmExports.__newString(JSON.stringify({
|
||||
contractTxId
|
||||
})));
|
||||
}, 1000);
|
||||
},
|
||||
clearTimeout,
|
||||
},
|
||||
env: {
|
||||
abort(messagePtr, fileNamePtr, line, column) {
|
||||
console.error("--------------------- Error message from AssemblyScript ----------------------");
|
||||
console.error(" " + wasmExports.__getString(messagePtr));
|
||||
console.error(
|
||||
' In file "' + wasmExports.__getString(fileNamePtr) + '"'
|
||||
);
|
||||
console.error(` on line ${line}, column ${column}.`);
|
||||
console.error("------------------------------------------------------------------------------\n");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getFn(idx) {
|
||||
return wasmExports.table.get(idx);
|
||||
}
|
||||
}
|
||||
|
||||
function formatGas(gas) {
|
||||
return gas * 1e-4;
|
||||
}
|
||||
@@ -28,6 +28,8 @@ import { GQLNodeInterface, GQLTagInterface } from './gqlResult';
|
||||
*
|
||||
*/
|
||||
export class SmartWeaveGlobal {
|
||||
gasUsed: number;
|
||||
gasLimit: number;
|
||||
transaction: Transaction;
|
||||
block: Block;
|
||||
arweave: Pick<Arweave, 'ar' | 'wallets' | 'utils' | 'crypto'>;
|
||||
@@ -46,7 +48,9 @@ export class SmartWeaveGlobal {
|
||||
|
||||
_activeTx?: GQLNodeInterface;
|
||||
|
||||
constructor(arweave: Arweave, contract: { id: string; owner: string }) {
|
||||
constructor(arweave: Arweave, contract: { id: string; owner: string }, gasLimit = Number.MAX_SAFE_INTEGER) {
|
||||
this.gasUsed = 0;
|
||||
this.gasLimit = gasLimit;
|
||||
this.unsafeClient = arweave;
|
||||
this.arweave = {
|
||||
ar: arweave.ar,
|
||||
|
||||
@@ -16,9 +16,11 @@ export class DebuggableExecutorFactory<Api> implements ExecutorFactory<Api> {
|
||||
|
||||
async create<State>(contractDefinition: ContractDefinition<State>): Promise<Api> {
|
||||
if (Object.prototype.hasOwnProperty.call(this.sourceCode, contractDefinition.txId)) {
|
||||
const enc = new TextEncoder(); // always utf-8
|
||||
|
||||
contractDefinition = {
|
||||
...contractDefinition,
|
||||
src: this.sourceCode[contractDefinition.txId]
|
||||
src: enc.encode(this.sourceCode[contractDefinition.txId])
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -88,12 +88,17 @@ export class ArweaveWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
async txData(id: string): Promise<string> {
|
||||
async txData(id: string): Promise<ArrayBuffer> {
|
||||
const response = await fetch(`${this.baseUrl}/${id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Unable to load tx data ${id}`);
|
||||
}
|
||||
const buffer = await response.arrayBuffer();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
async txDataString(id: string): Promise<string> {
|
||||
const buffer = await this.txData(id);
|
||||
return Arweave.utils.bufferToString(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
47
yarn.lock
47
yarn.lock
@@ -51,6 +51,11 @@
|
||||
http-errors "^1.7.3"
|
||||
object-path "^0.11.4"
|
||||
|
||||
"@assemblyscript/loader@^0.19.23":
|
||||
version "0.19.23"
|
||||
resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.19.23.tgz#7fccae28d0a2692869f1d1219d36093bc24d5e72"
|
||||
integrity sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==
|
||||
|
||||
"@babel/code-frame@7.12.11":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz"
|
||||
@@ -1769,7 +1774,7 @@ bluebird@^2.6.2, bluebird@^2.8.1:
|
||||
resolved "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz"
|
||||
integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
|
||||
|
||||
bn.js@^4.0.0, bn.js@^4.11.8, bn.js@^4.11.9:
|
||||
bn.js@^4.0.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9:
|
||||
version "4.12.0"
|
||||
resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz"
|
||||
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
|
||||
@@ -1862,6 +1867,20 @@ buffer-from@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer-pipe@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-pipe/-/buffer-pipe-0.0.0.tgz#186ec257d696e8e74c3051160a0e9e9a9811a387"
|
||||
integrity sha512-PvKbsvQOH4dcUyUEvQQSs3CIkkuPcOHt3gKnXwf4HsPKFDxSN7bkmICVIWgOmW/jx/fAEGGn4mIayIJPLs7G8g==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
buffer-pipe@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-pipe/-/buffer-pipe-0.0.2.tgz#960678ab517ca926dc1bfe231f402cbe2fe74442"
|
||||
integrity sha512-YlqzbWVqMv+xEeRyg0OXAJym3zAFTAIuku9l7okwxOXNDxbmSlL5o3QaF5k6IQ2iHO9o1OCo6tT4UkrQkI5VbQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
buffer-writer@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz"
|
||||
@@ -4693,6 +4712,14 @@ koa@^2.13.1:
|
||||
type-is "^1.6.16"
|
||||
vary "^1.1.2"
|
||||
|
||||
leb128@0.0.4, leb128@^0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/leb128/-/leb128-0.0.4.tgz#f96d698cf3ba5b677423abfe50b7e9b2df1463ff"
|
||||
integrity sha512-2zejk0fCIgY8RVcc/KzvyfpDio5Oo8HgPZmkrOmdwmbk0KpKpgD+JKwikxKk8cZYkANIhwHK50SNukkCm3XkCQ==
|
||||
dependencies:
|
||||
bn.js "^4.11.6"
|
||||
buffer-pipe "0.0.0"
|
||||
|
||||
leven@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz"
|
||||
@@ -6760,6 +6787,24 @@ walker@^1.0.7:
|
||||
dependencies:
|
||||
makeerror "1.0.12"
|
||||
|
||||
wasm-json-toolkit@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/wasm-json-toolkit/-/wasm-json-toolkit-0.2.3.tgz#51207da907a343152b02d0e97ee30c4a6e9f2308"
|
||||
integrity sha512-W0pESOST9hHFEmHq9kzMxAEhcPYuASdYCDw4FavKSyQKh3uOmH2slRXR/MhTKJY+gp1AauUDNd9DeE0cS4bV4A==
|
||||
dependencies:
|
||||
bn.js "^4.11.8"
|
||||
buffer-pipe "0.0.2"
|
||||
leb128 "0.0.4"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
wasm-metering@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/wasm-metering/-/wasm-metering-0.2.1.tgz#08220896e5e74b4ee3286636fd31d84e40544083"
|
||||
integrity sha512-YDlTPY4jspknNyDaVBQhLTuTYBh+39qI0P9F0grmR88NR4oh7qfgpTwZ2ly4oX2hHCj9KlIwhy2Yyez+3/wY2Q==
|
||||
dependencies:
|
||||
leb128 "^0.0.4"
|
||||
wasm-json-toolkit "0.2.3"
|
||||
|
||||
wcwidth@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz"
|
||||
|
||||
Reference in New Issue
Block a user