Skip to content

Commit

Permalink
feat(write): add write interface and base implementation on warp-cont…
Browse files Browse the repository at this point in the history
…ract
  • Loading branch information
Atticus committed Mar 22, 2024
1 parent 4bbe339 commit 6dfc969
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
11 changes: 8 additions & 3 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ArconnectSigner, ArweaveSigner } from 'arbundles';
import {
ArconnectSigner,
ArweaveSigner,
DataItem,
Transaction,
} from 'arbundles';

import {
ANTRecord,
Expand Down Expand Up @@ -85,14 +90,14 @@ export interface ReadContract {
}

export interface WriteContract {
writeInteraction<Input, State>({
writeInteraction<Input>({
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{
functionName: string;
inputs: Input;
}>): Promise<State>;
}>): Promise<Transaction | DataItem>;
}

export interface SmartWeaveContract<T> {
Expand Down
42 changes: 39 additions & 3 deletions src/common/contracts/warp-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Signer } from 'arbundles';
import { DataItem, Signer, Transaction } from 'arbundles';
import {
Contract,
LoggerFactory,
Expand All @@ -28,14 +28,18 @@ import {
ContractSigner,
EvaluationParameters,
ReadContract,
WriteContract,
} from '../../types.js';
import { FailedRequestError } from '../error.js';
import { isDataItem, isTransaction } from '../../utils/arweave.js';
import { FailedRequestError, WriteInteractionError } from '../error.js';

LoggerFactory.INST.setOptions({
logLevel: 'fatal',
});

export class WarpContract<T> implements BaseContract<T>, ReadContract {
export class WarpContract<T>
implements BaseContract<T>, ReadContract, WriteContract
{
private contract: Contract<T>;
private contractTxId: string;
private cacheUrl: string | undefined;
Expand Down Expand Up @@ -128,4 +132,36 @@ export class WarpContract<T> implements BaseContract<T>, ReadContract {

return evaluationResult.result;
}

async writeInteraction<Input>({
functionName,
inputs,
}: EvaluationParameters<{
functionName: string;
inputs: Input;
}>): Promise<Transaction | DataItem> {
// Sync state before writing
await this.syncState();
const { interactionTx } =
(await this.contract.writeInteraction<Input>({
function: functionName,
...inputs,
})) ?? {};

if (!interactionTx) {
throw new WriteInteractionError(
`Failed to write contract interaction ${functionName}`,
);
}
// Flexible way to return information on the transaction, aids in caching and redoployment if desired by simply refetching tx anchor and resigning.
if (isTransaction(interactionTx)) {
return interactionTx as Transaction;
} else if (isDataItem(interactionTx)) {
return interactionTx as DataItem;
}

throw new WriteInteractionError(
`Failed to write contract interaction ${functionName}`,
);
}
}
6 changes: 6 additions & 0 deletions src/common/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,9 @@ export class UnknownError extends BaseError {
super(message);
}
}

export class WriteInteractionError extends BaseError {
constructor(message: string) {
super(message);
}
}
19 changes: 19 additions & 0 deletions src/utils/arweave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DataItem, Transaction } from 'arbundles';
import Arweave from 'arweave';

import { BlockHeight } from '../common.js';
import { ARWEAVE_TX_REGEX } from '../constants.js';

Expand All @@ -24,3 +27,19 @@ export const validateArweaveId = (id: string): boolean => {
export function isBlockHeight(height: string | number): height is BlockHeight {
return height !== undefined && !isNaN(parseInt(height.toString()));
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isTransaction = (tx: any): tx is Transaction => {
const testTx = Arweave.init({}).createTransaction({ data: 'test' });
const testTxKeys = Object.keys(testTx);
const txKeys = Object.keys(tx);
return txKeys.every((key) => testTxKeys.includes(key));
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isDataItem = (item: any): item is DataItem => {
const testItem = new DataItem(Buffer.from('test'));
const testItemKeys = Object.keys(testItem);
const itemKeys = Object.keys(item);
return itemKeys.every((key) => testItemKeys.includes(key));
};

0 comments on commit 6dfc969

Please sign in to comment.