Skip to content

Commit

Permalink
feat(tests): added full integration test for UCM trading
Browse files Browse the repository at this point in the history
  • Loading branch information
atticusofsparta committed Dec 14, 2023
1 parent 965b72b commit 7cbcb3b
Show file tree
Hide file tree
Showing 20 changed files with 1,802 additions and 1,218 deletions.
2 changes: 1 addition & 1 deletion schemas/allow.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const allowSchema = {
},
txID: {
type: 'string',
pattern: '^[a-zA-Z0-9_-]{43}$'
pattern: '^[a-zA-Z0-9_-]{43}$',
},
},
required: ['qty', 'txID'],
Expand Down
2 changes: 1 addition & 1 deletion schemas/claim.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const claimSchema = {
},
txID: {
type: 'string',
pattern: '^[a-zA-Z0-9_-]{43}$'
pattern: '^[a-zA-Z0-9_-]{43}$',
},
},
required: ['qty', 'txID'],
Expand Down
6 changes: 3 additions & 3 deletions schemas/reject.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ const rejectSchema = {
pattern: '^[a-zA-Z0-9_-]{43}$',
},
qty: {
type: 'number',
minimum: 1,
}
type: 'number',
minimum: 1,
},
},
required: ['tx', 'qty'],
additionalProperties: false,
Expand Down
2 changes: 1 addition & 1 deletion schemas/transfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const transferSchema = {
},
},
required: ['target'],
additionalProperties: false,
additionalProperties: true,
};

module.exports = {
Expand Down
28 changes: 12 additions & 16 deletions src/actions/write/allow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
* 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 { of, Left, Right } from '../../lib/either'
import { Left, Right, of } from '../../lib/either';

export const allow = (state, action) => of({ state, action })
.chain(validate)
.map(update)
export const allow = (state, action) =>
of({ state, action }).chain(validate).map(update);

function update({ state, action }) {
state.balances[action.caller] -= action.input.qty;
Expand All @@ -35,29 +34,26 @@ function update({ state, action }) {
}

function validate({ state, action }) {
if (
!Number.isInteger(action.input.qty) ||
action.input.qty === undefined
) {
return Left("Invalid value for quantity. Must be an integer.");
if (!Number.isInteger(action.input.qty) || action.input.qty === undefined) {
return Left('Invalid value for quantity. Must be an integer.');
}
if (!action?.input?.target) {
return Left("No target specified.");
return Left('No target specified.');
}
if (action.input.target.length !== 43) {
return Left("Target is not valid!");
return Left('Target is not valid!');
}
if (action.input.target === SmartWeave.transaction.id) {
return Left("Cant setup claim to transfer a balance to itself");
return Left('Cant setup claim to transfer a balance to itself');
}
if (action.caller === action.input.target) {
return Left("Invalid balance transfer");
return Left('Invalid balance transfer');
}
if (!state.balances[action.caller]) {
return Left("Caller does not have a balance");
return Left('Caller does not have a balance');
}
if (state.balances[action.caller] < action.input.qty) {
return Left("Caller balance is not high enough.");
return Left('Caller balance is not high enough.');
}
return Right({ state, action });
}
}
23 changes: 10 additions & 13 deletions src/actions/write/claim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
* 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 { of, Left, Right } from '../../lib/either'
import { Left, Right, of } from '../../lib/either';

export const claim = (state, action) => of({ state, action })
.chain(validate)
.map(update)
export const claim = (state, action) =>
of({ state, action }).chain(validate).map(update);

function update({ state, action, idx }) {
if (!state.balances[action.caller]) {
Expand All @@ -33,28 +32,26 @@ function update({ state, action, idx }) {

function validate({ state, action }) {
if (!action.input.txID) {
return Left("txID is not found.");
return Left('txID is not found.');
}

if (!action.input.qty) {
return Left("claim quantity is not specified.");
return Left('claim quantity is not specified.');
}

const idx = state.claimable.findIndex(
(c) => c.txID === action.input.txID
);
const idx = state.claimable.findIndex((c) => c.txID === action.input.txID);

if (idx < 0) {
return Left("claimable not found.");
return Left('claimable not found.');
}

if (state.claimable[idx].qty !== action.input.qty) {
return Left("claimable qty is not equal to claim qty.");
return Left('claimable qty is not equal to claim qty.');
}

if (state.claimable[idx].to !== action.caller) {
return Left("claim is not addressed to caller.");
return Left('claim is not addressed to caller.');
}

return Right({ state, action, idx });
}
}
26 changes: 14 additions & 12 deletions src/actions/write/constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,29 @@
*/
export function constructor(state, action) {
if (action.input.args) {
state = {
records: {...state.records},
controllers: [...state.controllers],
...action.input.args}
state = {
records: state.records,
controllers: state.controllers,
...action.input.args,
};
}

if (!state.claimable) {
state.claimable = []
state.claimable = [];
}

if (!state.balances) {
state.balances = {}
state.balances = {};
}

if (!action.input?.args?.balances) {
state.balances[action.caller] = 100
state.balances[action.caller] = 100;
}

state.name = action.input?.args?.name ? action.input.args.name : 'AtomicAsset'
state.ticker = action.input?.args?.ticker ? action.input.args.ticker : 'AA'
state.name = action.input?.args?.name
? action.input.args.name
: 'AtomicAsset';
state.ticker = action.input?.args?.ticker ? action.input.args.ticker : 'AA';

return { state }

}
return { state };
}
49 changes: 25 additions & 24 deletions src/actions/write/reject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,50 @@
* 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 { AntAction, ANTState } from 'src/types'
import { fromNullable, Left, Right } from '../../lib/either'
import { ANTState, AntAction } from 'src/types';

export function reject(state: ANTState, action: AntAction) {
import { Left, Right, fromNullable } from '../../lib/either';

return fromNullable({state, action})
.chain(validate)
.map(update)
export function reject(state: ANTState, action: AntAction) {
return fromNullable({ state, action }).chain(validate).map(update);
}

function update({state, action}) {
const claim = state.claimable.find(c => c.txID === action.input.tx)
function update({ state, action }) {
const claim = state.claimable.find((c) => c.txID === action.input.tx);

if (!state.balances[claim.from]) {
state.balances[claim.from] = 0
state.balances[claim.from] = 0;
}
// add claim amount back to balance
state.balances[claim.from] += claim.qty
state.balances[claim.from] += claim.qty;

// remove claim
state.claimable = state.claimable.filter(c => c.txID !== claim.txID)
return {state}
state.claimable = state.claimable.filter((c) => c.txID !== claim.txID);
return { state };
}

function validate({state, action}) {
function validate({ state, action }) {
if (!action.input.tx) {
return Left('tx is required!')
return Left('tx is required!');
}
if (!action.input.qty) {
return Left('qty is required!')
return Left('qty is required!');
}
if (action.input.tx.length !== 43) {
return Left('tx is not valid')
return Left('tx is not valid');
}
if (!Number.isInteger(action.input.qty)) {
return Left('qty must be an integer')
return Left('qty must be an integer');
}
if (state.claimable.filter((c) => c.txID === action.input.tx).length !== 1) {
return Left('claim not found')
return Left('claim not found');
}
if (state.claimable.filter((c) => c.txID === action.input.tx)[0]?.to !== action.caller) {
return Left('claim in not addressed to caller')
if (
state.claimable.filter((c) => c.txID === action.input.tx)[0]?.to !==
action.caller
) {
return Left('claim in not addressed to caller');
}

return Right({state, action})
}
return Right({ state, action });
}
10 changes: 2 additions & 8 deletions src/actions/write/transferTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +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 {
INVALID_INPUT_MESSAGE,
NON_CONTRACT_OWNER_MESSAGE,
} from '../../constants';
import { INVALID_INPUT_MESSAGE } from '../../constants';
import { ANTState, AntAction, ContractResult } from '../../types';
// composed by ajv at build
import { validateTransferTokens } from '../../validations';
Expand All @@ -41,10 +38,6 @@ export const transferTokens = async (
throw new ContractError('Invalid token transfer');
}

if (caller !== owner) {
throw new ContractError(NON_CONTRACT_OWNER_MESSAGE);
}

if (
!balances[caller] ||
balances[caller] == undefined ||
Expand All @@ -58,6 +51,7 @@ export const transferTokens = async (
throw new ContractError(`Caller does not have a token balance!`);
}

delete balances[owner];
state.owner = target;
delete balances[caller];
balances[target] = 1;
Expand Down
16 changes: 8 additions & 8 deletions src/contract-ucm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import { ANTState, AntAction, ContractResult } from './types';
declare const ContractError;

function identity(v) {
return v
return v;
}

function handleError(msg) {
throw new ContractError(msg)
throw new ContractError(msg);
}

export async function handle(
Expand All @@ -46,18 +46,18 @@ export async function handle(
const input = action.input;

switch (input.function) {
case 'noop':
return { state }
case 'noop':
return { state };
case '__init':
return constructor(state, action);
case 'allow':
return allow(state, action).fold(handleError, identity)
return allow(state, action).fold(handleError, identity);
case 'reject':
return reject(state, action).fold(handleError, identity)
return reject(state, action).fold(handleError, identity);
case 'claim':
return claim(state, action).fold(handleError, identity)
return claim(state, action).fold(handleError, identity);
case 'transfer':
// atomic token has its own version, the ANT one should work as well.
// atomic token has its own version, the ANT one should work as well.
return await transferTokens(state, action);
case 'setRecord':
return await setRecord(state, action);
Expand Down
5 changes: 1 addition & 4 deletions src/lib/either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@
* @returns {Either}
*/


/* eslint-disable @typescript-eslint/no-unused-vars */


export const Right = (x) => ({
isLeft: false,
chain: (f) => f(x),
Expand All @@ -46,7 +44,7 @@ export const Right = (x) => ({
concat: (other) =>
other.fold(
(x) => other,
(y) => Right(x.concat(y))
(y) => Right(x.concat(y)),
),
traverse: (of, f) => f(x).map(Right),
map: (f) => Right(f(x)),
Expand Down Expand Up @@ -106,4 +104,3 @@ export const Either = {
};

/* eslint-enable @typescript-eslint/no-unused-vars */

21 changes: 0 additions & 21 deletions tests/setup.jest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import {
arweave,
createLocalWallet,
deployANTContract,
deployUCMContract,
deployUContract,
warp,
} from './utils/helper';

Expand All @@ -49,25 +47,6 @@ module.exports = async function () {
wallet,
});

const {contractTxId: ucmContractTxId, srcTxId: ucmSrcTxId} = await deployUCMContract({
warp,
owner,
wallet,
})

const {contractTxId: uContractTxId, srcTxId: uSrcTxId} = await deployUContract({
warp,
owner,
wallet,
})

process.env.ANT_CONTRACT_TX_ID = contractTxId;
process.env.ANT_SRC_TX_ID = srcTxId;

process.env.UCM_CONTRACT_TX_ID = ucmContractTxId;
process.env.UCM_SRC_TX_ID = ucmSrcTxId;

process.env.U_CONTRACT_TX_ID = uContractTxId;
process.env.U_SRC_TX_ID = uSrcTxId;

};
Loading

0 comments on commit 7cbcb3b

Please sign in to comment.