fix: reading owner of tx in strict mode (#306)
This commit is contained in:
@@ -155,4 +155,22 @@ describe('Testing the Profit Sharing Token', () => {
|
||||
expect(result.state.balances['uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M']).toEqual(10000000 + 555 + 333);
|
||||
expect(result.state.balances[overwrittenCaller]).toEqual(1000 - 333);
|
||||
});
|
||||
|
||||
describe('when in strict mode', () => {
|
||||
it('should properly extract owner from signature, using arweave wallet', async () => {
|
||||
const startBalance = (await pst.currentBalance(walletAddress)).balance;
|
||||
|
||||
await pst.writeInteraction(
|
||||
{
|
||||
function: 'transfer',
|
||||
target: 'uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M',
|
||||
qty: 100
|
||||
},
|
||||
{ strict: true }
|
||||
)
|
||||
|
||||
expect((await pst.currentBalance(walletAddress)).balance).toEqual(startBalance - 100);
|
||||
});
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import { InteractionResult } from '../core/modules/impl/HandlerExecutorFactory';
|
||||
import { EvaluationOptions, EvalStateResult } from '../core/modules/StateEvaluator';
|
||||
import { GQLNodeInterface } from '../legacy/gqlResult';
|
||||
import { ArTransfer, Tags, ArWallet } from './deploy/CreateContract';
|
||||
import { SignatureType } from './Signature';
|
||||
import { CustomSignature } from './Signature';
|
||||
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
|
||||
|
||||
export type CurrentTx = { interactionTxId: string; contractTxId: string };
|
||||
@@ -76,7 +76,7 @@ export interface Contract<State = unknown> {
|
||||
*
|
||||
* @param signer - either {@link ArWallet} that will be connected to this contract or custom {@link SigningFunction}
|
||||
*/
|
||||
connect(signature: ArWallet | SignatureType): Contract<State>;
|
||||
connect(signature: ArWallet | CustomSignature): Contract<State>;
|
||||
|
||||
/**
|
||||
* Allows to set ({@link EvaluationOptions})
|
||||
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
import { ArTransfer, ArWallet, emptyTransfer, Tags } from './deploy/CreateContract';
|
||||
import { InnerWritesEvaluator } from './InnerWritesEvaluator';
|
||||
import { generateMockVrf } from '../utils/vrf';
|
||||
import { Signature, SignatureType } from './Signature';
|
||||
import { Signature, CustomSignature } from './Signature';
|
||||
import { ContractDefinition } from '../core/ContractDefinition';
|
||||
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
|
||||
import { WarpFetchWrapper } from '../core/WarpFetchWrapper';
|
||||
@@ -366,13 +366,6 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
});
|
||||
|
||||
this.logger.debug('Tags with inner calls', tags);
|
||||
} else {
|
||||
if (strict) {
|
||||
const handlerResult = await this.callContract(input, undefined, undefined, tags, transfer, strict, vrf);
|
||||
if (handlerResult.type !== 'ok') {
|
||||
throw Error(`Cannot create interaction: ${handlerResult.errorMessage}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vrf) {
|
||||
@@ -394,6 +387,14 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
this.warp.environment === 'testnet',
|
||||
reward
|
||||
);
|
||||
|
||||
if (!this._evaluationOptions.internalWrites && strict) {
|
||||
const handlerResult = await this.callContract(input, interactionTx.owner, undefined, tags, transfer, strict, vrf);
|
||||
if (handlerResult.type !== 'ok') {
|
||||
throw Error(`Cannot create interaction: ${handlerResult.errorMessage}`);
|
||||
}
|
||||
}
|
||||
|
||||
return interactionTx;
|
||||
}
|
||||
|
||||
@@ -405,7 +406,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
return this._callStack;
|
||||
}
|
||||
|
||||
connect(signature: ArWallet | SignatureType): Contract<State> {
|
||||
connect(signature: ArWallet | CustomSignature): Contract<State> {
|
||||
this.signature = new Signature(this.warp, signature);
|
||||
return this;
|
||||
}
|
||||
@@ -467,14 +468,14 @@ export class HandlerBasedContract<State> implements Contract<State> {
|
||||
interactions
|
||||
? Promise.resolve(interactions)
|
||||
: await interactionsLoader.load(
|
||||
contractTxId,
|
||||
cachedState?.sortKey,
|
||||
// (1) we want to eagerly load dependant contract interactions and put them
|
||||
// in the interactions' loader cache
|
||||
// see: https://github.com/warp-contracts/warp/issues/198
|
||||
this.getToSortKey(upToSortKey),
|
||||
this._evaluationOptions
|
||||
)
|
||||
contractTxId,
|
||||
cachedState?.sortKey,
|
||||
// (1) we want to eagerly load dependant contract interactions and put them
|
||||
// in the interactions' loader cache
|
||||
// see: https://github.com/warp-contracts/warp/issues/198
|
||||
this.getToSortKey(upToSortKey),
|
||||
this._evaluationOptions
|
||||
)
|
||||
]);
|
||||
// (2) ...but we still need to return only interactions up to original "upToSortKey"
|
||||
if (cachedState?.sortKey) {
|
||||
|
||||
@@ -2,34 +2,24 @@ import Transaction from 'arweave/node/lib/transaction';
|
||||
import { Warp } from '../core/Warp';
|
||||
import { ArWallet } from './deploy/CreateContract';
|
||||
|
||||
export type SignatureType = 'arweave' | 'ethereum';
|
||||
export type SigningFunction = (tx: Transaction) => Promise<void>;
|
||||
export type SignatureType = { signer: SigningFunction; type: 'arweave' | 'ethereum' };
|
||||
export type CustomSignature = { signer: SigningFunction; type: SignatureType };
|
||||
|
||||
export class Signature {
|
||||
readonly signer: SigningFunction;
|
||||
readonly type: 'arweave' | 'ethereum';
|
||||
signer: SigningFunction;
|
||||
type: SignatureType;
|
||||
readonly warp: Warp;
|
||||
|
||||
constructor(warp: Warp, walletOrSignature: ArWallet | SignatureType) {
|
||||
constructor(warp: Warp, walletOrSignature: ArWallet | CustomSignature) {
|
||||
this.warp = warp;
|
||||
|
||||
if (this.isSignatureType(walletOrSignature)) {
|
||||
if (
|
||||
walletOrSignature.type !== 'arweave' &&
|
||||
(!(this.warp.environment == 'mainnet') || !(this.warp.interactionsLoader.type() == 'warp'))
|
||||
) {
|
||||
throw new Error(
|
||||
`Unable to use signing function of type: ${walletOrSignature.type} when not in mainnet environment or bundling is disabled.`
|
||||
);
|
||||
} else {
|
||||
this.signer = walletOrSignature.signer;
|
||||
this.type = walletOrSignature.type;
|
||||
}
|
||||
if (this.isCustomSignature(walletOrSignature)) {
|
||||
this.assertEnvForCustomSigner(walletOrSignature);
|
||||
this.signer = walletOrSignature.signer;
|
||||
this.type = walletOrSignature.type;
|
||||
} else {
|
||||
this.signer = async (tx: Transaction) => {
|
||||
await this.warp.arweave.transactions.sign(tx, walletOrSignature);
|
||||
};
|
||||
this.type = 'arweave';
|
||||
this.assignDefaultSigner(walletOrSignature);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +29,23 @@ export class Signature {
|
||||
}
|
||||
}
|
||||
|
||||
private isSignatureType(signature: ArWallet | SignatureType): signature is SignatureType {
|
||||
return (signature as SignatureType).signer !== undefined;
|
||||
private assignDefaultSigner(walletOrSignature) {
|
||||
this.signer = async (tx: Transaction) => {
|
||||
await this.warp.arweave.transactions.sign(tx, walletOrSignature);
|
||||
};
|
||||
this.type = 'arweave';
|
||||
}
|
||||
|
||||
private assertEnvForCustomSigner(walletOrSignature: CustomSignature) {
|
||||
if (walletOrSignature.type !== 'arweave' &&
|
||||
(!(this.warp.environment == 'mainnet') || !(this.warp.interactionsLoader.type() == 'warp'))) {
|
||||
throw new Error(
|
||||
`Unable to use signing function of type: ${walletOrSignature.type} when not in mainnet environment or bundling is disabled.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private isCustomSignature(signature: ArWallet | CustomSignature): signature is CustomSignature {
|
||||
return (signature as CustomSignature).signer !== undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { JWKInterface } from 'arweave/node/lib/wallet';
|
||||
import { SignatureType } from '../../contract/Signature';
|
||||
import { CustomSignature } from '../../contract/Signature';
|
||||
import { Source } from './Source';
|
||||
import { EvaluationOptions } from '../../core/modules/StateEvaluator';
|
||||
import { WarpPluginType } from '../../core/WarpPlugin';
|
||||
@@ -29,7 +29,7 @@ export const BUNDLR_NODES = ['node1', 'node2'] as const;
|
||||
export type BundlrNodeType = typeof BUNDLR_NODES[number];
|
||||
|
||||
export interface CommonContractData {
|
||||
wallet: ArWallet | SignatureType;
|
||||
wallet: ArWallet | CustomSignature;
|
||||
initState: string;
|
||||
tags?: Tags;
|
||||
transfer?: ArTransfer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ArWallet } from './CreateContract';
|
||||
import { SourceData } from './impl/SourceImpl';
|
||||
import { SignatureType } from '../../contract/Signature';
|
||||
import { CustomSignature } from '../../contract/Signature';
|
||||
import Transaction from 'arweave/node/lib/transaction';
|
||||
export interface Source {
|
||||
/**
|
||||
@@ -8,7 +8,7 @@ export interface Source {
|
||||
* @param sourceData - contract source data
|
||||
* @param wallet - either Arweave wallet or custom signature type
|
||||
*/
|
||||
createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction>;
|
||||
createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction>;
|
||||
|
||||
/**
|
||||
* allows to save contract source
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable */
|
||||
import Arweave from 'arweave';
|
||||
import Transaction from 'arweave/node/lib/transaction';
|
||||
import { Signature, SignatureType } from '../../../contract/Signature';
|
||||
import { WarpFetchWrapper } from '../../../core/WarpFetchWrapper';
|
||||
import { Signature, CustomSignature } from '../../../contract/Signature';
|
||||
import { SmartWeaveTags } from '../../../core/SmartWeaveTags';
|
||||
import { Warp } from '../../../core/Warp';
|
||||
import { WARP_GW_URL } from '../../../core/WarpFactory';
|
||||
@@ -182,7 +182,7 @@ export class DefaultCreateContract implements CreateContract {
|
||||
}
|
||||
}
|
||||
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
|
||||
return this.source.createSourceTx(sourceData, wallet);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { LoggerFactory } from '../../../logging/LoggerFactory';
|
||||
import { Source } from '../Source';
|
||||
import { Buffer } from 'redstone-isomorphic';
|
||||
import { Warp } from '../../../core/Warp';
|
||||
import { Signature, SignatureType } from '../../../contract/Signature';
|
||||
import { Signature, CustomSignature } from '../../../contract/Signature';
|
||||
import Transaction from 'arweave/node/lib/transaction';
|
||||
import { WARP_GW_URL } from '../../../core/WarpFactory';
|
||||
import { TagsParser } from '../../../core/modules/impl/TagsParser';
|
||||
@@ -32,9 +32,9 @@ export class SourceImpl implements Source {
|
||||
private readonly logger = LoggerFactory.INST.create('Source');
|
||||
private signature: Signature;
|
||||
|
||||
constructor(private readonly warp: Warp) {}
|
||||
constructor(private readonly warp: Warp) { }
|
||||
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
|
||||
this.logger.debug('Creating new contract source');
|
||||
|
||||
const { src, wasmSrcCodeDir, wasmGlueCode } = sourceData;
|
||||
@@ -235,7 +235,7 @@ function dummyImports(moduleImports: WebAssembly.ModuleImportDescriptor[]) {
|
||||
if (!Object.prototype.hasOwnProperty.call(imports, moduleImport.module)) {
|
||||
imports[moduleImport.module] = {};
|
||||
}
|
||||
imports[moduleImport.module][moduleImport.name] = function () {};
|
||||
imports[moduleImport.module][moduleImport.name] = function () { };
|
||||
});
|
||||
|
||||
return imports;
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from './WarpPlugin';
|
||||
import { SortKeyCache } from '../cache/SortKeyCache';
|
||||
import { ContractDefinition, SrcCache } from './ContractDefinition';
|
||||
import { SignatureType } from '../contract/Signature';
|
||||
import { CustomSignature } from '../contract/Signature';
|
||||
import { SourceData } from '../contract/deploy/impl/SourceImpl';
|
||||
import Transaction from 'arweave/node/lib/transaction';
|
||||
|
||||
@@ -97,7 +97,7 @@ export class Warp {
|
||||
return await this.createContract.register(id, bundlrNode);
|
||||
}
|
||||
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
|
||||
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
|
||||
return await this.createContract.createSourceTx(sourceData, wallet);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user