feat: interaction data item (#430)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@ bundles/
|
||||
logs
|
||||
|
||||
target
|
||||
metafile.json
|
||||
@@ -2,6 +2,8 @@ const { build } = require('esbuild');
|
||||
const rimraf = require('rimraf');
|
||||
const plugin = require('node-stdlib-browser/helpers/esbuild/plugin');
|
||||
const stdLibBrowser = require('node-stdlib-browser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const clean = async () => {
|
||||
return new Promise((resolve) => {
|
||||
@@ -24,7 +26,7 @@ const runBuild = async () => {
|
||||
};
|
||||
|
||||
console.log('Building web bundle esm.');
|
||||
await build({
|
||||
const result = await build({
|
||||
...buildConfig,
|
||||
minify: true,
|
||||
// metafile: true,
|
||||
@@ -34,6 +36,7 @@ const runBuild = async () => {
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// fs.writeFileSync(path.join(__dirname, 'metafile.json'), JSON.stringify(result.metafile));
|
||||
console.log('Building web bundle iife.');
|
||||
await build({
|
||||
...buildConfig,
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
"safe-stable-stringify": "2.4.1",
|
||||
"stream-buffers": "^3.0.2",
|
||||
"unzipit": "^1.4.0",
|
||||
"warp-arbundles": "1.0.1",
|
||||
"warp-isomorphic": "1.0.4",
|
||||
"warp-wasm-metering": "1.0.1"
|
||||
},
|
||||
@@ -117,8 +118,8 @@
|
||||
"ts-jest": "^28.0.7",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.9.5",
|
||||
"warp-contracts-plugin-deploy": "1.0.8-beta.0",
|
||||
"warp-contracts-plugin-vm2": "1.0.0",
|
||||
"warp-contracts-plugin-deploy": "1.0.8",
|
||||
"warp-contracts-plugin-vm2": "1.0.1",
|
||||
"warp-contracts-plugin-vrf": "^1.0.3",
|
||||
"ws": "^8.11.0"
|
||||
},
|
||||
|
||||
@@ -43,9 +43,7 @@ describe('Wallet', () => {
|
||||
it(`should throw for custom signing function and ethereum signature type`, () => {
|
||||
expect(() => {
|
||||
new Signature(warp, { signer: sampleFunction, type: 'ethereum' });
|
||||
}).toThrow(
|
||||
`Unable to use signing function of type: ethereum when not in mainnet environment or bundling is disabled.`
|
||||
);
|
||||
}).toThrow(`Unable to use signing function with signature of type: ethereum.`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,9 +68,18 @@ describe('Wallet', () => {
|
||||
expect(sut.type).toStrictEqual('arweave');
|
||||
});
|
||||
|
||||
it(`should throw for custom signing function and arweave signature type`, () => {
|
||||
expect(() => {
|
||||
new Signature(warp, { signer: sampleFunction, type: 'arweave' });
|
||||
}).toThrow(`Unable to use signing function when bundling is enabled.`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('in testnet environment when gw url set to arweave', () => {
|
||||
const warp = WarpFactory.forTestnet(defaultCacheOptions, true);
|
||||
|
||||
it(`should set correct signature for custom signing function and arweave signature type`, () => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'arweave' });
|
||||
|
||||
expect(sut.signer).toEqual(sampleFunction);
|
||||
expect(sut.type).toEqual('arweave');
|
||||
});
|
||||
@@ -104,12 +111,10 @@ describe('Wallet', () => {
|
||||
expect(sut.type).toEqual('arweave');
|
||||
});
|
||||
|
||||
it(`should throw for custom signing function and arweave signature type`, () => {
|
||||
it(`should throw for custom signing function and ethereum signature type`, () => {
|
||||
expect(() => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'ethereum' });
|
||||
}).toThrow(
|
||||
`Unable to use signing function of type: ethereum when not in mainnet environment or bundling is disabled.`
|
||||
);
|
||||
}).toThrow(`Unable to use signing function with signature of type: ethereum.`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -132,16 +137,16 @@ describe('Wallet', () => {
|
||||
expect(sut.type).toStrictEqual('arweave');
|
||||
});
|
||||
|
||||
it(`should set correct signature for custom signing function and arweave signature type`, () => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'arweave' });
|
||||
expect(sut.signer.toString().replace(/\s+/g, '')).toEqual(sampleFunction.toString().replace(/\s+/g, ''));
|
||||
expect(sut.type).toEqual('arweave');
|
||||
it(`should throw for custom signing function and ethereum signature type`, () => {
|
||||
expect(() => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'ethereum' });
|
||||
}).toThrow(`Unable to use signing function when bundling is enabled.`);
|
||||
});
|
||||
|
||||
it(`should set correct signature for custom signing function and ethereum signature type`, () => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'ethereum' });
|
||||
expect(sut.signer.toString().replace(/\s+/g, '')).toEqual(sampleFunction.toString().replace(/\s+/g, ''));
|
||||
expect(sut.signer).toEqual(sampleFunction);
|
||||
it(`should throw for custom signing function and arweave signature type`, () => {
|
||||
expect(() => {
|
||||
const sut = new Signature(warp, { signer: sampleFunction, type: 'arweave' });
|
||||
}).toThrow(`Unable to use signing function when bundling is enabled.`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -157,9 +162,9 @@ describe('Wallet', () => {
|
||||
});
|
||||
|
||||
it('should call getAddress for customSignature, if getAddress provided', async () => {
|
||||
const warp = WarpFactory.forMainnet();
|
||||
const warp = WarpFactory.forMainnet(defaultCacheOptions, true);
|
||||
const customSignature: CustomSignature = {
|
||||
type: 'ethereum',
|
||||
type: 'arweave',
|
||||
signer: sampleFunction,
|
||||
getAddress: () => Promise.resolve('owner')
|
||||
};
|
||||
@@ -171,39 +176,36 @@ describe('Wallet', () => {
|
||||
});
|
||||
|
||||
it('should call getAddress for customSignature, if getAddress NOT provided', async () => {
|
||||
const warp = WarpFactory.forMainnet();
|
||||
const warp = WarpFactory.forMainnet(defaultCacheOptions, true);
|
||||
const customSignature: CustomSignature = {
|
||||
type: 'ethereum',
|
||||
type: 'arweave',
|
||||
signer: async (tx) => {
|
||||
tx.owner = 'owner';
|
||||
Promise.resolve(tx);
|
||||
}
|
||||
};
|
||||
|
||||
const signature = new Signature(warp, customSignature);
|
||||
|
||||
const address = await signature.getAddress();
|
||||
expect(address).toStrictEqual('owner');
|
||||
expect(address).toStrictEqual('47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU');
|
||||
});
|
||||
|
||||
it('should use cached valued from getAddress', async () => {
|
||||
const warp = WarpFactory.forMainnet();
|
||||
const mockedSigner = jest.fn(async (tx) => {
|
||||
tx.owner = 'owner';
|
||||
});
|
||||
const warp = WarpFactory.forMainnet(defaultCacheOptions, true);
|
||||
const customSignature: CustomSignature = {
|
||||
type: 'ethereum',
|
||||
signer: mockedSigner
|
||||
type: 'arweave',
|
||||
signer: async (tx) => {
|
||||
Promise.resolve(tx);
|
||||
}
|
||||
};
|
||||
|
||||
const signature = new Signature(warp, customSignature);
|
||||
|
||||
const address = await signature.getAddress();
|
||||
expect(address).toStrictEqual('owner');
|
||||
expect(address).toStrictEqual('47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU');
|
||||
|
||||
const cachedAddress = await signature.getAddress();
|
||||
expect(cachedAddress).toStrictEqual('owner');
|
||||
|
||||
expect(mockedSigner).toBeCalledTimes(1);
|
||||
expect(cachedAddress).toStrictEqual('47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ArTransfer, Tags, ArWallet } from './deploy/CreateContract';
|
||||
import { CustomSignature } from './Signature';
|
||||
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
|
||||
import { InteractionState } from './states/InteractionState';
|
||||
import { Signer } from 'warp-arbundles';
|
||||
|
||||
export type BenchmarkStats = { gatewayCommunication: number; stateEvaluation: number; total: number };
|
||||
|
||||
@@ -87,9 +88,9 @@ export interface Contract<State = unknown> {
|
||||
* i.e. whether called contract's function required "caller" info)
|
||||
* Connecting a signer MUST be done before "writeInteraction" and "bundleInteraction".
|
||||
*
|
||||
* @param signer - either {@link ArWallet} that will be connected to this contract or custom {@link SigningFunction}
|
||||
* @param signer - either {@link ArWallet} that will be connected to this contract, custom {@link SigningFunction} or {@link Signer}
|
||||
*/
|
||||
connect(signature: ArWallet | CustomSignature): Contract<State>;
|
||||
connect(signature: ArWallet | CustomSignature | Signer): Contract<State>;
|
||||
|
||||
/**
|
||||
* Allows to set ({@link EvaluationOptions})
|
||||
|
||||
@@ -14,13 +14,13 @@ import { InteractionsSorter } from '../core/modules/InteractionsSorter';
|
||||
import { DefaultEvaluationOptions, EvalStateResult, EvaluationOptions } from '../core/modules/StateEvaluator';
|
||||
import { WARP_TAGS } from '../core/KnownTags';
|
||||
import { Warp } from '../core/Warp';
|
||||
import { createDummyTx, createInteractionTx } from '../legacy/create-interaction-tx';
|
||||
import { createDummyTx, createInteractionTagsList, createInteractionTx } from '../legacy/create-interaction-tx';
|
||||
import { GQLNodeInterface } from '../legacy/gqlResult';
|
||||
import { Benchmark } from '../logging/Benchmark';
|
||||
import { LoggerFactory } from '../logging/LoggerFactory';
|
||||
import { Evolve } from '../plugins/Evolve';
|
||||
import { ArweaveWrapper } from '../utils/ArweaveWrapper';
|
||||
import { getJsonResponse, sleep, stripTrailingSlash } from '../utils/utils';
|
||||
import { getJsonResponse, isBrowser, sleep, stripTrailingSlash } from '../utils/utils';
|
||||
import {
|
||||
BenchmarkStats,
|
||||
Contract,
|
||||
@@ -35,12 +35,13 @@ import { CustomSignature, Signature } from './Signature';
|
||||
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
|
||||
import { WarpFetchWrapper } from '../core/WarpFetchWrapper';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { TransactionStatusResponse } from '../utils/types/arweave-types';
|
||||
import { Tag, TransactionStatusResponse } from '../utils/types/arweave-types';
|
||||
import { InteractionState } from './states/InteractionState';
|
||||
import { ContractInteractionState } from './states/ContractInteractionState';
|
||||
import { Crypto } from 'warp-isomorphic';
|
||||
import { VrfPluginFunctions } from '../core/WarpPlugin';
|
||||
import Arweave from 'arweave';
|
||||
import { createData, tagsExceedLimit, DataItem, Signer } from 'warp-arbundles';
|
||||
|
||||
/**
|
||||
* An implementation of {@link Contract} that is backwards compatible with current style
|
||||
@@ -48,6 +49,7 @@ import Arweave from 'arweave';
|
||||
*
|
||||
* It requires {@link ExecutorFactory} that is using {@link HandlerApi} generic type.
|
||||
*/
|
||||
|
||||
export class HandlerBasedContract<State> implements Contract<State> {
|
||||
private readonly logger = LoggerFactory.INST.create('HandlerBasedContract');
|
||||
|
||||
@@ -261,6 +263,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
const bundleInteraction = interactionsLoader.type() == 'warp' && !effectiveDisableBundling;
|
||||
|
||||
this._signature.checkNonArweaveSigningAvailability(bundleInteraction);
|
||||
this._signature.checkBundlerSignerAvailability(bundleInteraction);
|
||||
|
||||
if (
|
||||
bundleInteraction &&
|
||||
@@ -274,6 +277,10 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
throw new Error('Vrf generation is only available for bundle interaction');
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
throw new Error(`Input should be a truthy value: ${JSON.stringify(input)}`);
|
||||
}
|
||||
|
||||
if (bundleInteraction) {
|
||||
return await this.bundleInteraction(input, {
|
||||
tags: effectiveTags,
|
||||
@@ -322,34 +329,86 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
): Promise<WriteInteractionResponse | null> {
|
||||
this.logger.info('Bundle interaction input', input);
|
||||
|
||||
const interactionTx = await this.createInteraction(
|
||||
const interactionDataItem = await this.createInteractionDataItem(
|
||||
input,
|
||||
options.tags,
|
||||
emptyTransfer,
|
||||
options.strict,
|
||||
true,
|
||||
options.vrf
|
||||
);
|
||||
|
||||
const response = this._warpFetchWrapper.fetch(
|
||||
`${stripTrailingSlash(this._evaluationOptions.sequencerUrl)}/gateway/sequencer/register`,
|
||||
`${stripTrailingSlash(this._evaluationOptions.sequencerUrl)}/gateway/v2/sequencer/register`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(interactionTx),
|
||||
headers: {
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Type': 'application/octet-stream',
|
||||
Accept: 'application/json'
|
||||
}
|
||||
},
|
||||
body: interactionDataItem.getRaw()
|
||||
}
|
||||
);
|
||||
|
||||
const dataItemId = await interactionDataItem.id;
|
||||
|
||||
return {
|
||||
bundlrResponse: await getJsonResponse(response),
|
||||
originalTxId: interactionTx.id
|
||||
originalTxId: dataItemId
|
||||
};
|
||||
}
|
||||
|
||||
private async createInteractionDataItem<Input>(
|
||||
input: Input,
|
||||
tags: Tags,
|
||||
transfer: ArTransfer,
|
||||
strict: boolean,
|
||||
vrf = false
|
||||
) {
|
||||
if (this._evaluationOptions.internalWrites) {
|
||||
// it modifies tags
|
||||
await this.discoverInternalWrites<Input>(input, tags, transfer, strict, vrf);
|
||||
}
|
||||
|
||||
if (vrf) {
|
||||
tags.push(new Tag(WARP_TAGS.REQUEST_VRF, 'true'));
|
||||
}
|
||||
|
||||
const interactionTags = createInteractionTagsList(
|
||||
this._contractTxId,
|
||||
input,
|
||||
this.warp.environment === 'testnet',
|
||||
tags
|
||||
);
|
||||
|
||||
if (tagsExceedLimit(interactionTags)) {
|
||||
throw new Error(`Interaction tags exceed limit of 4096 bytes.`);
|
||||
}
|
||||
|
||||
const data = Math.random().toString().slice(-4);
|
||||
const bundlerSigner = this._signature.bundlerSigner;
|
||||
|
||||
if (!bundlerSigner) {
|
||||
throw new Error(
|
||||
`Signer not set correctly. If you connect wallet through 'use_wallet', please remember that it only works when bundling is disabled.`
|
||||
);
|
||||
}
|
||||
|
||||
let interactionDataItem: DataItem;
|
||||
if (isBrowser() && bundlerSigner.signer?.signDataItem) {
|
||||
interactionDataItem = await bundlerSigner.signDataItem(data, interactionTags);
|
||||
} else {
|
||||
interactionDataItem = createData(data, bundlerSigner, { tags: interactionTags });
|
||||
await interactionDataItem.sign(bundlerSigner);
|
||||
}
|
||||
|
||||
// TODO: for ethereum owner is set to public key and not the address!!
|
||||
if (!this._evaluationOptions.internalWrites && strict) {
|
||||
await this.checkInteractionInStrictMode(interactionDataItem.owner, input, tags, transfer, strict, vrf);
|
||||
}
|
||||
|
||||
return interactionDataItem;
|
||||
}
|
||||
|
||||
private async createInteraction<Input>(
|
||||
input: Input,
|
||||
tags: Tags,
|
||||
@@ -365,10 +424,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
}
|
||||
|
||||
if (vrf) {
|
||||
tags.push({
|
||||
name: WARP_TAGS.REQUEST_VRF,
|
||||
value: 'true'
|
||||
});
|
||||
tags.push(new Tag(WARP_TAGS.REQUEST_VRF, 'true'));
|
||||
}
|
||||
|
||||
const interactionTx = await createInteractionTx(
|
||||
@@ -385,20 +441,28 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
);
|
||||
|
||||
if (!this._evaluationOptions.internalWrites && strict) {
|
||||
const { arweave } = this.warp;
|
||||
const caller =
|
||||
this._signature.type == 'arweave'
|
||||
? await arweave.wallets.ownerToAddress(interactionTx.owner)
|
||||
: interactionTx.owner;
|
||||
const handlerResult = await this.callContract(input, 'write', caller, undefined, tags, transfer, strict, vrf);
|
||||
if (handlerResult.type !== 'ok') {
|
||||
throw Error('Cannot create interaction: ' + JSON.stringify(handlerResult.error || handlerResult.errorMessage));
|
||||
}
|
||||
await this.checkInteractionInStrictMode(interactionTx.owner, input, tags, transfer, strict, vrf);
|
||||
}
|
||||
|
||||
return interactionTx;
|
||||
}
|
||||
|
||||
private async checkInteractionInStrictMode<Input>(
|
||||
owner: string,
|
||||
input: Input,
|
||||
tags: Tags,
|
||||
transfer: ArTransfer,
|
||||
strict: boolean,
|
||||
vrf: boolean
|
||||
) {
|
||||
const { arweave } = this.warp;
|
||||
const caller = this._signature.type == 'arweave' ? await arweave.wallets.ownerToAddress(owner) : owner;
|
||||
const handlerResult = await this.callContract(input, 'write', caller, undefined, tags, transfer, strict, vrf);
|
||||
if (handlerResult.type !== 'ok') {
|
||||
throw Error('Cannot create interaction: ' + JSON.stringify(handlerResult.error || handlerResult.errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
txId(): string {
|
||||
return this._contractTxId;
|
||||
}
|
||||
@@ -407,7 +471,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
return this._callStack;
|
||||
}
|
||||
|
||||
connect(signature: ArWallet | CustomSignature): Contract<State> {
|
||||
connect(signature: ArWallet | CustomSignature | Signer): Contract<State> {
|
||||
this._signature = new Signature(this.warp, signature);
|
||||
return this;
|
||||
}
|
||||
@@ -975,10 +1039,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
this.logger.debug('Callstack', callStack.print());
|
||||
|
||||
innerWrites.forEach((contractTxId) => {
|
||||
tags.push({
|
||||
name: WARP_TAGS.INTERACT_WRITE,
|
||||
value: contractTxId
|
||||
});
|
||||
tags.push(new Tag(WARP_TAGS.INTERACT_WRITE, contractTxId));
|
||||
});
|
||||
|
||||
this.logger.debug('Tags with inner calls', tags);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Warp } from '../core/Warp';
|
||||
import { ArWallet } from './deploy/CreateContract';
|
||||
import { Transaction } from '../utils/types/arweave-types';
|
||||
import { BundlerSigner } from './deploy/DataItem';
|
||||
import { JWKInterface } from 'arweave/node/lib/wallet';
|
||||
import { ArweaveSigner, Signer as BundlerSigner } from 'warp-arbundles';
|
||||
import { isBrowser } from '../utils/utils';
|
||||
|
||||
export type SignatureType = 'arweave' | 'ethereum';
|
||||
export type SigningFunction = (tx: Transaction) => Promise<void>;
|
||||
@@ -16,13 +18,13 @@ Different types which can be used to sign transaction or data item
|
||||
- ArWallet - default option for signing Arweave transactions, either JWKInterface or 'use_wallet'
|
||||
- CustomSignature - object with `signer` field - a custom signing function which takes transaction as a parameter and requires signing it
|
||||
on the client side and `type` field of type SignatureType which indicates the wallet's chain, either 'arweave' or 'ethereum'
|
||||
- Signer - arbundles specific class which allows to sign data items (only this type can be used when bundling is enabled and data items
|
||||
are being created)
|
||||
- Signer - arbundles specific class which allows to sign data items (works with data items - when bundling is enabled)
|
||||
*/
|
||||
export type SignatureProvider = ArWallet | CustomSignature | BundlerSigner;
|
||||
|
||||
export class Signature {
|
||||
signer: SigningFunction;
|
||||
bundlerSigner: BundlerSigner;
|
||||
readonly type: SignatureType;
|
||||
readonly warp: Warp;
|
||||
private readonly signatureProviderType: 'CustomSignature' | 'ArWallet' | 'BundlerSigner';
|
||||
@@ -40,8 +42,11 @@ export class Signature {
|
||||
} else if (this.isValidBundlerSignature(walletOrSignature)) {
|
||||
this.signatureProviderType = 'BundlerSigner';
|
||||
this.type = decodeBundleSignatureType(walletOrSignature.signatureType);
|
||||
this.bundlerSigner = walletOrSignature;
|
||||
} else {
|
||||
this.assignArweaveSigner(walletOrSignature);
|
||||
this.bundlerSigner =
|
||||
typeof walletOrSignature == 'string' ? null : new ArweaveSigner(walletOrSignature as JWKInterface);
|
||||
this.signatureProviderType = 'ArWallet';
|
||||
this.type = 'arweave';
|
||||
}
|
||||
@@ -76,19 +81,22 @@ export class Signature {
|
||||
}
|
||||
}
|
||||
|
||||
private async deduceSignerBySigning() {
|
||||
private async deduceSignerBySigning(): Promise<string> {
|
||||
const { arweave } = this.warp;
|
||||
|
||||
const dummyTx = await arweave.createTransaction({
|
||||
data: Math.random().toString().slice(-4),
|
||||
reward: '72600854',
|
||||
last_tx: 'p7vc1iSP6bvH_fCeUFa9LqoV5qiyW-jdEKouAT0XMoSwrNraB9mgpi29Q10waEpO'
|
||||
});
|
||||
await this.signer(dummyTx);
|
||||
|
||||
if (this.type === 'ethereum') {
|
||||
return dummyTx.owner;
|
||||
} else if (this.type === 'arweave') {
|
||||
if (this.signatureProviderType == 'BundlerSigner') {
|
||||
try {
|
||||
return await this.bundlerSigner.getAddress();
|
||||
} catch (e) {
|
||||
throw new Error(`Could not get address from the signer. Is the 'getAddress' implementation correct?'`);
|
||||
}
|
||||
} else if (this.signatureProviderType == 'ArWallet' || this.signatureProviderType == 'CustomSignature') {
|
||||
const dummyTx = await arweave.createTransaction({
|
||||
data: Math.random().toString().slice(-4),
|
||||
reward: '72600854',
|
||||
last_tx: 'p7vc1iSP6bvH_fCeUFa9LqoV5qiyW-jdEKouAT0XMoSwrNraB9mgpi29Q10waEpO'
|
||||
});
|
||||
await (this.signer as SigningFunction)(dummyTx);
|
||||
return arweave.wallets.ownerToAddress(dummyTx.owner);
|
||||
} else {
|
||||
throw Error('Unknown Signature::type');
|
||||
@@ -101,6 +109,18 @@ export class Signature {
|
||||
}
|
||||
}
|
||||
|
||||
checkBundlerSignerAvailability(bundling: boolean): void {
|
||||
if (bundling && isBrowser() && this.signatureProviderType != 'BundlerSigner') {
|
||||
throw new Error(`Only wallet of type 'Signer' is allowed when bundling is enabled and in browser.`);
|
||||
}
|
||||
|
||||
if ((!bundling || this.warp.environment == 'local') && this.signatureProviderType == 'BundlerSigner') {
|
||||
throw new Error(
|
||||
`Only wallet of type 'ArWallet' or 'CustomSignature' is allowed when bundling is disabled or in local environment.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private assignArweaveSigner(walletOrSignature) {
|
||||
this.signer = async (tx: Transaction) => {
|
||||
await this.warp.arweave.transactions.sign(tx, walletOrSignature);
|
||||
@@ -108,19 +128,17 @@ export class Signature {
|
||||
}
|
||||
|
||||
private assertEnvForCustomSigner(signatureType: SignatureType) {
|
||||
if (signatureType === 'arweave') {
|
||||
return;
|
||||
if (this.warp.interactionsLoader.type() === 'warp') {
|
||||
throw new Error(`Unable to use signing function when bundling is enabled.`);
|
||||
}
|
||||
|
||||
if (!['mainnet', 'testnet'].includes(this.warp.environment) || this.warp.interactionsLoader.type() !== 'warp') {
|
||||
throw new Error(
|
||||
`Unable to use signing function of type: ${signatureType} when not in mainnet environment or bundling is disabled.`
|
||||
);
|
||||
if (signatureType == 'ethereum') {
|
||||
throw new Error(`Unable to use signing function with signature of type: ${signatureType}.`);
|
||||
}
|
||||
}
|
||||
|
||||
private isCustomSignature(signature: SignatureProvider): signature is CustomSignature {
|
||||
return (signature as CustomSignature).signer !== undefined;
|
||||
return (signature as CustomSignature).signer !== undefined && (signature as CustomSignature).type !== undefined;
|
||||
}
|
||||
|
||||
private isValidBundlerSignature(signature: SignatureProvider): signature is BundlerSigner {
|
||||
|
||||
@@ -4,8 +4,9 @@ import { EvaluationOptions } from '../../core/modules/StateEvaluator';
|
||||
import { Source } from './Source';
|
||||
import { BundlerSigner } from './DataItem';
|
||||
import { CustomSignature } from '../Signature';
|
||||
import { Tag } from '../../utils/types/arweave-types';
|
||||
|
||||
export type Tags = { name: string; value: string }[];
|
||||
export type Tags = Tag[];
|
||||
|
||||
export type ArWallet = JWKInterface | 'use_wallet';
|
||||
|
||||
|
||||
@@ -3,14 +3,15 @@ import { SMART_WEAVE_TAGS, WARP_TAGS } from '../core/KnownTags';
|
||||
import { GQLNodeInterface } from './gqlResult';
|
||||
import { TagsParser } from '../core/modules/impl/TagsParser';
|
||||
import { SigningFunction } from '../contract/Signature';
|
||||
import { BlockData, CreateTransactionInterface, Transaction } from '../utils/types/arweave-types';
|
||||
import { BlockData, CreateTransactionInterface, Tag, Transaction } from '../utils/types/arweave-types';
|
||||
import { Tags } from '../contract/deploy/CreateContract';
|
||||
|
||||
export async function createInteractionTx<Input>(
|
||||
arweave: Arweave,
|
||||
signer: SigningFunction,
|
||||
contractId: string,
|
||||
input: Input,
|
||||
tags: { name: string; value: string }[],
|
||||
tags: Tags,
|
||||
target = '',
|
||||
winstonQty = '0',
|
||||
dummy = false,
|
||||
@@ -42,24 +43,8 @@ export async function createInteractionTx<Input>(
|
||||
|
||||
const interactionTx = await arweave.createTransaction(options);
|
||||
|
||||
if (!input) {
|
||||
throw new Error(`Input should be a truthy value: ${JSON.stringify(input)}`);
|
||||
}
|
||||
|
||||
if (tags && tags.length) {
|
||||
for (const tag of tags) {
|
||||
interactionTx.addTag(tag.name.toString(), tag.value.toString());
|
||||
}
|
||||
}
|
||||
interactionTx.addTag(SMART_WEAVE_TAGS.APP_NAME, 'SmartWeaveAction');
|
||||
// use real SDK version here?
|
||||
interactionTx.addTag(SMART_WEAVE_TAGS.APP_VERSION, '0.3.0');
|
||||
interactionTx.addTag(SMART_WEAVE_TAGS.SDK, 'Warp');
|
||||
interactionTx.addTag(SMART_WEAVE_TAGS.CONTRACT_TX_ID, contractId);
|
||||
interactionTx.addTag(SMART_WEAVE_TAGS.INPUT, JSON.stringify(input));
|
||||
if (isTestnet) {
|
||||
interactionTx.addTag(WARP_TAGS.WARP_TESTNET, '1.0.0');
|
||||
}
|
||||
const interactionTags = createInteractionTagsList(contractId, input, isTestnet, tags);
|
||||
interactionTags.forEach((t) => interactionTx.addTag(t.name, t.value));
|
||||
|
||||
if (signer) {
|
||||
await signer(interactionTx);
|
||||
@@ -114,3 +99,30 @@ export function createDummyTx(tx: Transaction, from: string, block: BlockData):
|
||||
bundledIn: null
|
||||
};
|
||||
}
|
||||
|
||||
export function createInteractionTagsList<Input>(
|
||||
contractId: string,
|
||||
input: Input,
|
||||
isTestnet: boolean,
|
||||
customTags?: Tags
|
||||
) {
|
||||
const interactionTags: Tags = [];
|
||||
|
||||
if (customTags && customTags.length) {
|
||||
for (const customTag of customTags) {
|
||||
interactionTags.push(new Tag(customTag.name.toString(), customTag.value.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
interactionTags.push(new Tag(SMART_WEAVE_TAGS.APP_NAME, 'SmartWeaveAction'));
|
||||
// use real SDK version here?
|
||||
interactionTags.push(new Tag(SMART_WEAVE_TAGS.APP_VERSION, '0.3.0'));
|
||||
interactionTags.push(new Tag(SMART_WEAVE_TAGS.SDK, 'Warp'));
|
||||
interactionTags.push(new Tag(SMART_WEAVE_TAGS.CONTRACT_TX_ID, contractId));
|
||||
interactionTags.push(new Tag(SMART_WEAVE_TAGS.INPUT, JSON.stringify(input)));
|
||||
if (isTestnet) {
|
||||
interactionTags.push(new Tag(WARP_TAGS.WARP_TESTNET, '1.0.0'));
|
||||
}
|
||||
|
||||
return interactionTags;
|
||||
}
|
||||
|
||||
30
yarn.lock
30
yarn.lock
@@ -2365,7 +2365,7 @@ arweave-stream-tx@^1.1.0:
|
||||
dependencies:
|
||||
exponential-backoff "^3.1.0"
|
||||
|
||||
arweave@1.13.7:
|
||||
arweave@1.13.7, arweave@^1.13.7:
|
||||
version "1.13.7"
|
||||
resolved "https://registry.yarnpkg.com/arweave/-/arweave-1.13.7.tgz#cda8534c833baec372a7052c61f53b4e39a886d7"
|
||||
integrity sha512-Hv+x2bSI6UyBHpuVbUDMMpMje1ETfpJWj52kKfz44O0IqDRi/LukOkkDUptup1p6OT6KP1/DdpnUnsNHoskFeA==
|
||||
@@ -7472,19 +7472,29 @@ walker@^1.0.8:
|
||||
dependencies:
|
||||
makeerror "1.0.12"
|
||||
|
||||
warp-contracts-plugin-deploy@1.0.8-beta.0:
|
||||
version "1.0.8-beta.0"
|
||||
resolved "https://registry.yarnpkg.com/warp-contracts-plugin-deploy/-/warp-contracts-plugin-deploy-1.0.8-beta.0.tgz#c4c95a57d53a5ae2a50c0907f94ac74e6bcdbada"
|
||||
integrity sha512-bA8K9QHuIvE1XzWpFYmAR5+xisanAzfInxx0ekMwlGVFiDWciWcVAFNefLUa5iFHuHlDpqgDQvUpsd6lg7Wx8g==
|
||||
warp-arbundles@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/warp-arbundles/-/warp-arbundles-1.0.1.tgz#c816ee44aacd90e0214b1b7db8028c6d5b468770"
|
||||
integrity sha512-bWyF8PoS5D2M8yk7YAT/DFi4pzoPxfXaS1o9eEelcD5SU42PW/wVxwzrvn6pLaHFIK5Zys15V2eGd+8X1Ty62Q==
|
||||
dependencies:
|
||||
arweave "^1.13.7"
|
||||
base64url "^3.0.1"
|
||||
buffer "^6.0.3"
|
||||
warp-isomorphic "^1.0.4"
|
||||
|
||||
warp-contracts-plugin-deploy@1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/warp-contracts-plugin-deploy/-/warp-contracts-plugin-deploy-1.0.8.tgz#94e9841ea3f68d09e9c1bbd483efa84a2c541901"
|
||||
integrity sha512-5KF12X0g2L1BrGGWGidkJAex3AK0c3y3KQDT1J/5OGCmldgesogKOKADw4VrzcdOvV/CbjdyiIXy5XB9cYXPGQ==
|
||||
dependencies:
|
||||
arbundles "^0.7.3"
|
||||
arlocal "^1.1.59"
|
||||
node-stdlib-browser "^1.2.0"
|
||||
|
||||
warp-contracts-plugin-vm2@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/warp-contracts-plugin-vm2/-/warp-contracts-plugin-vm2-1.0.0.tgz#f55914a228102f3bda7dafc197c395078fa0e190"
|
||||
integrity sha512-3XubaZ9eeRbBtMDwmTAewZk6WYgtcg9g44vATqH5vmn2wdPWIBcrBX3gA7XQIDbqPcLPpIgifMDZiQJSNwYZDA==
|
||||
warp-contracts-plugin-vm2@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/warp-contracts-plugin-vm2/-/warp-contracts-plugin-vm2-1.0.1.tgz#0c1749f998508e8559a4627afc574ff80577353c"
|
||||
integrity sha512-ogECglCyZZ3vF7nm9RqkDA+b8AwHmoda8Uv2oYIMyxm7haLjTMtZNY+QvqDbI3b/B/MR+nX1nwdTe7KIUqqQjQ==
|
||||
dependencies:
|
||||
bignumber.js "^9.1.1"
|
||||
vm2 "^3.9.16"
|
||||
@@ -7505,7 +7515,7 @@ warp-isomorphic@1.0.0:
|
||||
buffer "^6.0.3"
|
||||
undici "^5.8.0"
|
||||
|
||||
warp-isomorphic@1.0.4:
|
||||
warp-isomorphic@1.0.4, warp-isomorphic@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/warp-isomorphic/-/warp-isomorphic-1.0.4.tgz#1017eba260e0f0228b33b94b9e36a1afe54e09d8"
|
||||
integrity sha512-W77IoLjq/eu5bY1uRrlmVt5lLDoIHeZ0ozJ/j67FTnxvZRXu887biEnom1nx8q1UgOKyJh8eQYFQaE2FLlKhFg==
|
||||
|
||||
Reference in New Issue
Block a user