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

feat!: refactor predicate support to work through Wallet and Provider directly #461

Merged
merged 1 commit into from
Aug 19, 2022
Merged
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
6 changes: 6 additions & 0 deletions packages/interfaces/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ export abstract class AbstractWallet {
export type AddressLike = AbstractAddress | AbstractWallet;

export type ContractIdLike = AbstractAddress | AbstractContract;

export abstract class AbstractPredicate {
abstract bytes: Uint8Array;
abstract address: AbstractAddress;
abstract types?: ReadonlyArray<any>;
}
10 changes: 5 additions & 5 deletions packages/predicate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
"dependencies": {
"@fuel-ts/abi-coder": "workspace:*",
"@fuel-ts/address": "workspace:*",
"@fuel-ts/constants": "workspace:*",
"@fuel-ts/contract": "workspace:*",
"@fuel-ts/interfaces": "workspace:*",
"@fuel-ts/keystore": "workspace:*",
"@fuel-ts/math": "workspace:*",
"@fuel-ts/providers": "workspace:*",
"@fuel-ts/wallet": "workspace:*",
"@fuel-ts/transactions": "workspace:*",
"@ethersproject/bytes": "^5.5.0"
},
"devDependencies": {
"@fuel-ts/constants": "workspace:*",
"@fuel-ts/math": "workspace:*",
"@fuel-ts/providers": "workspace:*"
}
}
119 changes: 93 additions & 26 deletions packages/predicate/src/predicate.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Address } from '@fuel-ts/address';
import { NativeAssetId } from '@fuel-ts/constants';
import type { AbstractAddress } from '@fuel-ts/interfaces';
import type { BigNumberish } from '@fuel-ts/math';
import { Provider } from '@fuel-ts/providers';
import type { Wallet } from '@fuel-ts/wallet';
Expand Down Expand Up @@ -29,30 +30,31 @@ const setupPredicate = async (
amountToPredicate: BigNumberish,
predicate: Predicate
): Promise<bigint> => {
await predicate.submitPredicate(wallet, amountToPredicate);
await wallet.submitPredicate(predicate.address, amountToPredicate);

// collect balance from predicate to prevent flaky tests where predicate address gets "filled up"
return predicate.getPredicateBalance(wallet);
return wallet.provider.getBalance(predicate.address, NativeAssetId);
};

const assertResults = async (
wallet: Wallet,
receiverAddress: Address,
receiverAddress: AbstractAddress,
initialPredicateBalance: bigint,
initialReceiverBalance: bigint,
amountToPredicate: bigint,
predicate: Predicate
predicate: Predicate,
isSkippingInitialReceiverBalance = false
): Promise<void> => {
// Check there are UTXO locked with the predicate hash
expect(initialPredicateBalance).toBeGreaterThanOrEqual(amountToPredicate);
expect(initialReceiverBalance).toEqual(0n);
!isSkippingInitialReceiverBalance && expect(initialReceiverBalance).toEqual(0n);

// Check the balance of the receiver
const finalReceiverBalance = await wallet.provider.getBalance(receiverAddress, NativeAssetId);
expect(initialReceiverBalance + initialPredicateBalance).toEqual(finalReceiverBalance);

// Check we spent the entire predicate hash input
const finalPredicateBalance = await predicate.getPredicateBalance(wallet);
const finalPredicateBalance = await wallet.provider.getBalance(predicate.address, NativeAssetId);
expect(finalPredicateBalance).toEqual(0n);
};

Expand Down Expand Up @@ -102,7 +104,7 @@ describe('Predicate', () => {
const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);
const initialReceiverBalance = await wallet.provider.getBalance(receiverAddress, NativeAssetId);

await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress);
await wallet.provider.submitSpendPredicate(predicate, initialPredicateBalance, receiverAddress);

await assertResults(
wallet,
Expand All @@ -114,16 +116,36 @@ describe('Predicate', () => {
);
});

it('can call a no-arg Predicate that returns false', async () => {
const receiverAddress = Address.fromRandom();
it('can call a no-arg Predicate that returns true, via wallet', async () => {
const wallet = await setup();
const amountToPredicate = 10n;
const predicate = new Predicate(testPredicateTrue);

const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);
const initialReceiverBalance = await wallet.provider.getBalance(wallet.address, NativeAssetId);

await wallet.submitSpendPredicate(predicate, initialPredicateBalance);

await assertResults(
wallet,
wallet.address,
initialPredicateBalance,
initialReceiverBalance,
amountToPredicate,
predicate,
true
);
});

it('can call a no-arg Predicate that returns false, via wallet', async () => {
const wallet = await setup();
const amountToPredicate = 10n;
const predicate = new Predicate(testPredicateFalse);

const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);

await expect(async () => {
await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress);
await wallet.submitSpendPredicate(predicate, initialPredicateBalance);
}).rejects.toThrow('Invalid transaction');
});

Expand All @@ -136,9 +158,12 @@ describe('Predicate', () => {
const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);
const initialReceiverBalance = await wallet.provider.getBalance(receiverAddress, NativeAssetId);

await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [
'0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a',
]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
['0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a']
);

await assertResults(
wallet,
Expand All @@ -150,6 +175,29 @@ describe('Predicate', () => {
);
});

it('can call a Coin predicate which returns true with valid predicate data [address], via wallet', async () => {
const wallet = await setup();
const amountToPredicate = 10n;
const predicate = new Predicate(testPredicateAddress, AddressAbiInputs);

const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);
const initialReceiverBalance = await wallet.provider.getBalance(wallet.address, NativeAssetId);

await wallet.submitSpendPredicate(predicate, initialPredicateBalance, [
'0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a',
]);

await assertResults(
wallet,
wallet.address,
initialPredicateBalance,
initialReceiverBalance,
amountToPredicate,
predicate,
true
);
});

it('can call a Coin predicate which returns false with invalid predicate data [address]', async () => {
const receiverAddress = Address.fromRandom();
const wallet = await setup();
Expand All @@ -164,9 +212,12 @@ describe('Predicate', () => {
expect(initialReceiverBalance).toEqual(0n);

await expect(async () => {
await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [
'0xbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbada',
]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
['0xbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbada']
);
}).rejects.toThrow('Invalid transaction');
});

Expand All @@ -179,7 +230,12 @@ describe('Predicate', () => {
const initialPredicateBalance = await setupPredicate(wallet, amountToPredicate, predicate);
const initialReceiverBalance = await wallet.provider.getBalance(receiverAddress, NativeAssetId);

await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [1078]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
[1078]
);

await assertResults(
wallet,
Expand All @@ -205,7 +261,12 @@ describe('Predicate', () => {
expect(initialReceiverBalance).toEqual(0n);

await expect(async () => {
await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [100]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
[100]
);
}).rejects.toThrow('Invalid transaction');
});

Expand All @@ -222,9 +283,12 @@ describe('Predicate', () => {
has_account: true,
total_complete: 100n,
};
await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [
validation,
]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
[validation]
);

await assertResults(
wallet,
Expand All @@ -249,9 +313,12 @@ describe('Predicate', () => {
};

await expect(async () => {
await predicate.submitSpendPredicate(wallet, initialPredicateBalance, receiverAddress, [
validation,
]);
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
[validation]
);
}).rejects.toThrow('Invalid transaction');
});

Expand All @@ -273,8 +340,8 @@ describe('Predicate', () => {

let failed;
try {
await predicate.submitSpendPredicate(
wallet,
await wallet.provider.submitSpendPredicate(
predicate,
initialPredicateBalance,
receiverAddress,
[validation],
Expand Down
Loading