Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exposing interactRead in swGlobal object #1

Open
wants to merge 1 commit into
base: ppe/interact-read-timestamp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/__tests__/contract-interact.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SmartWeaveGlobal } from '../smartweave-global';

const swGlobal = new SmartWeaveGlobal({} as any, null);
const swGlobal = new SmartWeaveGlobal({} as any, null, null);
const contractSrc = `
function handle(action, state) {
return {result: SmartWeave.block}
Expand Down
19 changes: 10 additions & 9 deletions src/contract-create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Arweave from 'arweave';
import Transaction from 'arweave/node/lib/transaction';
import { JWKInterface } from 'arweave/node/lib/wallet';
import {Wallet} from "./utils";

/**
* Simulates the creation of a new contract from a contract, so that the cost for the creation can be checked
Expand All @@ -13,11 +13,11 @@ import { JWKInterface } from 'arweave/node/lib/wallet';
*/
export async function simulateCreateContractFromSource(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
initState: string,
contractSrc: string,
): Promise<Transaction> {
const srcTx = await arweave.createTransaction({ data: contractSrc }, wallet);
const srcTx = await arweave.createTransaction({data: contractSrc}, wallet);

srcTx.addTag('App-Name', 'SmartWeaveContractSource');
srcTx.addTag('App-Version', '0.3.0');
Expand Down Expand Up @@ -47,14 +47,14 @@ export async function simulateCreateContractFromSource(
*/
export async function simulateCreateContractFromTx(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
srcTxId: string,
state: string,
tags: { name: string; value: string }[] = [],
target: string = '',
winstonQty: string = '',
): Promise<Transaction> {
let contractTX = await arweave.createTransaction({ data: state }, wallet);
let contractTX = await arweave.createTransaction({data: state}, wallet);

if (target && winstonQty && target.length && +winstonQty > 0) {
contractTX = await arweave.createTransaction(
Expand Down Expand Up @@ -92,11 +92,11 @@ export async function simulateCreateContractFromTx(
*/
export async function createContract(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
contractSrc: string,
initState: string,
): Promise<string> {
const srcTx = await arweave.createTransaction({ data: contractSrc }, wallet);
const srcTx = await arweave.createTransaction({data: contractSrc}, wallet);

srcTx.addTag('App-Name', 'SmartWeaveContractSource');
srcTx.addTag('App-Version', '0.3.0');
Expand All @@ -112,6 +112,7 @@ export async function createContract(
throw new Error('Unable to write Contract Source.');
}
}

/**
* Create a new contract from an existing contract source tx, with an initial state.
* Returns the contract id.
Expand All @@ -126,14 +127,14 @@ export async function createContract(
*/
export async function createContractFromTx(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
srcTxId: string,
state: string,
tags: { name: string; value: string }[] = [],
target: string = '',
winstonQty: string = '',
) {
let contractTX = await arweave.createTransaction({ data: state }, wallet);
let contractTX = await arweave.createTransaction({data: state}, wallet);

if (target && winstonQty && target.length && +winstonQty > 0) {
contractTX = await arweave.createTransaction(
Expand Down
34 changes: 18 additions & 16 deletions src/contract-interact.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import Arweave from 'arweave';
import { CreateTransactionInterface } from 'arweave/node/common';
import {CreateTransactionInterface} from 'arweave/node/common';
import Transaction from 'arweave/node/lib/transaction';
import { JWKInterface } from 'arweave/node/lib/wallet';
import { loadContract } from './contract-load';
import { readContract } from './contract-read';
import { execute, ContractInteraction, ContractInteractionResult } from './contract-step';
import { unpackTags } from './utils';
import { BlockData } from 'arweave/node/blocks';
import {loadContract} from './contract-load';
import {readContract} from './contract-read';
import {ContractInteraction, ContractInteractionResult, execute} from './contract-step';
import {OptionalWallet, unpackTags, Wallet} from './utils';
import {BlockData} from 'arweave/node/blocks';

/**
* Writes an interaction on the blockchain.
Expand All @@ -24,7 +23,7 @@ import { BlockData } from 'arweave/node/blocks';
*/
export async function interactWrite(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
contractId: string,
input: any,
tags: { name: string; value: string }[] = [],
Expand Down Expand Up @@ -56,7 +55,7 @@ export async function interactWrite(
*/
export async function simulateInteractWrite(
arweave: Arweave,
wallet: JWKInterface,
wallet: Wallet,
contractId: string,
input: any,
tags: { name: string; value: string }[] = [],
Expand Down Expand Up @@ -84,7 +83,7 @@ export async function simulateInteractWrite(
*/
export async function interactWriteDryRun(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
contractId: string,
input: any,
tags: { name: string; value: string }[] = [],
Expand All @@ -94,7 +93,7 @@ export async function interactWriteDryRun(
fromParam: any = {},
contractInfoParam: any = {},
): Promise<ContractInteractionResult> {
const { handler, swGlobal } = contractInfoParam || (await loadContract(arweave, contractId));
const { handler, swGlobal } = contractInfoParam || (await loadContract(arweave, contractId, wallet));
const latestState = myState || (await readContract(arweave, contractId));
const from = fromParam || (await arweave.wallets.getAddress(wallet));

Expand All @@ -118,6 +117,9 @@ export async function interactWriteDryRun(
* This will load a contract to its latest state, and do a dry run of an interaction,
* without writing anything to the chain.
*
* Note: this seems to be somewhat similar interactWriteDryRun, but with the option
* to pass custom interaction transaction data.
*
* @param arweave an Arweave client instance
* @param tx a signed transaction
* @param contractId the Transaction Id of the contract
Expand All @@ -128,14 +130,14 @@ export async function interactWriteDryRun(
*/
export async function interactWriteDryRunCustom(
arweave: Arweave,
tx: any,
tx: Transaction,
contractId: string,
input: any,
myState: any = {},
fromParam: any = {},
contractInfoParam: any = {},
): Promise<ContractInteractionResult> {
const { handler, swGlobal } = contractInfoParam || (await loadContract(arweave, contractId));
const { handler, swGlobal } = contractInfoParam || (await loadContract(arweave, contractId, undefined));
const latestState = myState || (await readContract(arweave, contractId));
const from = fromParam;

Expand Down Expand Up @@ -167,14 +169,14 @@ export async function interactWriteDryRunCustom(
*/
export async function interactRead(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet' | undefined,
wallet: OptionalWallet,
contractId: string,
input: any,
tags: { name: string; value: string }[] = [],
target: string = '',
winstonQty: string = '',
): Promise<any> {
const { handler, swGlobal } = await loadContract(arweave, contractId);
const { handler, swGlobal } = await loadContract(arweave, contractId, wallet);
const latestState = await readContract(arweave, contractId);
const from = wallet ? await arweave.wallets.getAddress(wallet) : '';

Expand All @@ -196,7 +198,7 @@ export async function interactRead(

async function createTx(
arweave: Arweave,
wallet: JWKInterface | 'use_wallet',
wallet: Wallet,
contractId: string,
input: any,
tags: { name: string; value: string }[],
Expand Down
20 changes: 11 additions & 9 deletions src/contract-load.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Arweave from 'arweave';
import * as clarity from '@weavery/clarity';
import { getTag, normalizeContractSource } from './utils';
import { ContractHandler } from './contract-step';
import { SmartWeaveGlobal } from './smartweave-global';
import {getTag, normalizeContractSource, OptionalWallet} from './utils';
import {ContractHandler} from './contract-step';
import {SmartWeaveGlobal} from './smartweave-global';
import BigNumber from 'bignumber.js';

/**
Expand All @@ -11,7 +11,7 @@ import BigNumber from 'bignumber.js';
* @param arweave an Arweave client instance
* @param contractID the Transaction Id of the contract
*/
export async function loadContract(arweave: Arweave, contractID: string, contractSrcTXID?: string) {
export async function loadContract(arweave: Arweave, contractID: string, wallet: OptionalWallet, contractSrcTXID?: string) {
// Generate an object containing the details about a contract in one place.
const contractTX = await arweave.transactions.get(contractID);
const contractOwner = await arweave.wallets.ownerToAddress(contractTX.owner);
Expand All @@ -20,19 +20,20 @@ export async function loadContract(arweave: Arweave, contractID: string, contrac

const minFee = getTag(contractTX, 'Min-Fee');
const contractSrcTX = await arweave.transactions.get(contractSrcTXID);
const contractSrc = contractSrcTX.get('data', { decode: true, string: true });
const contractSrc = contractSrcTX.get('data', {decode: true, string: true});

let state: string;
if (getTag(contractTX, 'Init-State')) {
state = getTag(contractTX, 'Init-State');
} else if (getTag(contractTX, 'Init-State-TX')) {
const stateTX = await arweave.transactions.get(getTag(contractTX, 'Init-State-TX'));
state = stateTX.get('data', { decode: true, string: true });
state = stateTX.get('data', {decode: true, string: true});
} else {
state = contractTX.get('data', { decode: true, string: true });
state = contractTX.get('data', {decode: true, string: true});
}

const { handler, swGlobal } = createContractExecutionEnvironment(arweave, contractSrc, contractID, contractOwner);
const {handler, swGlobal}
= createContractExecutionEnvironment(arweave, contractSrc, contractID, contractOwner, wallet);

return {
id: contractID,
Expand Down Expand Up @@ -63,9 +64,10 @@ export function createContractExecutionEnvironment(
contractSrc: string,
contractId: string,
contractOwner: string,
wallet: OptionalWallet
) {
const returningSrc = normalizeContractSource(contractSrc);
const swGlobal = new SmartWeaveGlobal(arweave, { id: contractId, owner: contractOwner });
const swGlobal = new SmartWeaveGlobal(arweave, {id: contractId, owner: contractOwner}, wallet);
const getContractFunction = new Function(returningSrc); // eslint-disable-line

return {
Expand Down
8 changes: 5 additions & 3 deletions src/contract-read.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Arweave from 'arweave';
import { loadContract } from './contract-load';
import { arrayToHex, log } from './utils';
import {arrayToHex, log, OptionalWallet} from './utils';
import { execute, ContractInteraction } from './contract-step';
import { InteractionTx } from './interaction-tx';
import GQLResultInterface, { GQLEdgeInterface, GQLTransactionsResultInterface } from './interfaces/gqlResult';
Expand All @@ -16,19 +16,21 @@ import SmartWeaveError, { SmartWeaveErrorType } from './errors';
* @param contractId the Transaction Id of the contract
* @param height if specified the contract will be replayed only to this block height
* @param returnValidity if true, the function will return valid and invalid transaction IDs along with the state
* @param wallet wallet of the caller. Required if contract's code is making "interactRead" calls to other contracts.
*/
export async function readContract(
arweave: Arweave,
contractId: string,
height?: number,
returnValidity?: boolean,
wallet?: OptionalWallet
): Promise<any> {
if (!height) {
const networkInfo = await arweave.network.getInfo();
height = networkInfo.height;
}

const loadPromise = loadContract(arweave, contractId).catch((err) => {
const loadPromise = loadContract(arweave, contractId, wallet).catch((err) => {
const error: SmartWeaveError = new SmartWeaveError(SmartWeaveErrorType.CONTRACT_NOT_FOUND, {
message: `Contract having txId: ${contractId} not found`,
requestedTxId: contractId,
Expand Down Expand Up @@ -110,7 +112,7 @@ export async function readContract(
if (contractSrc !== state.evolve) {
try {
console.log('inside evolve!', state.evolve);
contractInfo = await loadContract(arweave, contractId, evolve);
contractInfo = await loadContract(arweave, contractId, wallet, evolve);
handler = contractInfo.handler;
} catch (e) {
const error: SmartWeaveError = new SmartWeaveError(SmartWeaveErrorType.CONTRACT_NOT_FOUND, {
Expand Down
21 changes: 20 additions & 1 deletion src/smartweave-global.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Arweave from 'arweave';
import { InteractionTx } from './interaction-tx';
import { readContract } from './contract-read';
import {interactRead} from "./contract-interact";
import {OptionalWallet} from "./utils";

/**
*
Expand Down Expand Up @@ -36,9 +38,11 @@ export class SmartWeaveGlobal {
owner: string;
};
unsafeClient: Arweave;
wallet: OptionalWallet; // wallet of the caller that is interacting with the contract.

contracts: {
readContractState: (contractId: string) => Promise<any>;
interactReadResult: (contractId: string, input: any) => Promise<any>;
};

_activeTx?: InteractionTx;
Expand All @@ -47,7 +51,7 @@ export class SmartWeaveGlobal {
return !this._activeTx;
}

constructor(arweave: Arweave, contract: { id: string; owner: string }) {
constructor(arweave: Arweave, contract: { id: string; owner: string }, wallet: OptionalWallet) {
this.unsafeClient = arweave;
this.arweave = {
ar: arweave.ar,
Expand All @@ -66,7 +70,22 @@ export class SmartWeaveGlobal {
height || (this._isDryRunning ? Number.POSITIVE_INFINITY : this.block.height),
returnValidity,
),
interactReadResult: (calleContractTxId: string, input: any): Promise<any> => {
if (wallet === undefined) {
throw `Caller's wallet not set in SmartWeaveGlobal and is to call interactRead on other contract.
Did you forget to pass wallet to the originally called SDK function?
`;
// alternatively return here sth like "{result: 'error-no-wallet'}",
// as handling such case might be handled by contract itself.
}
return interactRead(
arweave,
wallet,
calleContractTxId,
input);
}
};
this.wallet = wallet;
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Transaction from 'arweave/node/lib/transaction';
import Arweave from 'arweave';
import {JWKInterface} from "arweave/node/lib/wallet";

export type Wallet = JWKInterface | 'use_wallet';
export type OptionalWallet = Wallet | undefined;

interface UnformattedTag {
name: string;
Expand Down