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

placeSellTokenOrder & placeBuyTokenOrder #42

Merged
merged 6 commits into from
May 7, 2019
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dependencies": {
"@augmint/contracts": "1.0.9",
"bignumber.js": "5.0.0",
"bn.js": "4.11.8",
"dotenv": "8.0.0",
"ulog": "2.0.0-beta.6",
"web3": "1.0.0-beta.36"
Expand Down
34 changes: 20 additions & 14 deletions src/Augmint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ export class Augmint {
Object.keys(stubs).forEach(stub => {
const role = stub;
const contractListStub = stubs[stub];
deployedEnvironment.addRole(
role,
contractListStub.map(contractStub => new DeployedContract(contractStub))
);
deployedEnvironment.addRole(role, contractListStub.map(contractStub => new DeployedContract(contractStub)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this some autoformatting? did the settings change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep i've noticed. it's happened before too. I suspect that @rszaloki doesn't have prettier format on save set or something else different in our editor. We should make sure we sync our setting

});
return deployedEnvironment;
}
Expand All @@ -52,7 +49,7 @@ export class Augmint {
this.ethereumConnection = ethereumConnection;
this.web3 = this.ethereumConnection.web3;
if (!environment) {
const networkId:string = this.ethereumConnection.networkId.toString(10);
const networkId: string = this.ethereumConnection.networkId.toString(10);
const selectedDeployedEnvironment = deployments.find(
(item: DeployedEnvironment) => item.name === networkId
);
Expand Down Expand Up @@ -94,15 +91,19 @@ export class Augmint {

get token(): AugmintToken {
if (!this._token) {
const tokenContract: DeployedContract<TokenAEur> = this.deployedEnvironment.getLatestContract(AugmintContracts.TokenAEur);
const tokenContract: DeployedContract<TokenAEur> = this.deployedEnvironment.getLatestContract(
AugmintContracts.TokenAEur
);
this._token = new AugmintToken(tokenContract.connect(this.web3), { web3: this.web3 });
}
return this._token;
}

get rates(): Rates {
if (!this._rates) {
const ratesContract: DeployedContract<RatesInstance> = this.deployedEnvironment.getLatestContract(AugmintContracts.Rates);
const ratesContract: DeployedContract<RatesInstance> = this.deployedEnvironment.getLatestContract(
AugmintContracts.Rates
);
this._rates = new Rates(ratesContract.connect(this.web3), {
decimals: this.token.decimals,
decimalsDiv: this.token.decimalsDiv,
Expand All @@ -115,10 +116,11 @@ export class Augmint {

get exchange(): Exchange {
if (!this._exchange) {
const exchangeContract: DeployedContract<ExchangeInstance> = this.deployedEnvironment.getLatestContract(AugmintContracts.Exchange);
const exchangeContract: DeployedContract<ExchangeInstance> = this.deployedEnvironment.getLatestContract(
AugmintContracts.Exchange
);
this._exchange = new Exchange(exchangeContract.connect(this.web3), {
decimalsDiv: this.token.decimalsDiv,
peggedSymbol: this.token.peggedSymbol,
token: this.token,
rates: this.rates,
ONE_ETH_IN_WEI: constants.ONE_ETH_IN_WEI,
ethereumConnection: this.ethereumConnection
Expand All @@ -131,9 +133,13 @@ export class Augmint {
return this._environment;
}

public getLegacyTokens():AugmintToken[] {
const legacyTokens: Array<DeployedContract<TokenAEur>> = this.deployedEnvironment.getLegacyContracts(AugmintContracts.TokenAEur);
return legacyTokens.map(tokenContract => new AugmintToken(tokenContract.connect(this.web3), { web3: this.web3 }))
public getLegacyTokens(): AugmintToken[] {
const legacyTokens: Array<DeployedContract<TokenAEur>> = this.deployedEnvironment.getLegacyContracts(
AugmintContracts.TokenAEur
);
return legacyTokens.map(
tokenContract => new AugmintToken(tokenContract.connect(this.web3), { web3: this.web3 })
);
}

// myaugmint.getLegacyExchanges(Augmint.constants.SUPPORTED_LEGACY_EXCHANGES)
Expand All @@ -149,7 +155,7 @@ export class Augmint {
}
const options = {
decimalsDiv: this.token.decimalsDiv,
peggedSymbol: this.token.peggedSymbol,
token: this.token, // FIXME: This should come from the exchange contract's augmintToken property
rates: this.rates,
ONE_ETH_IN_WEI: constants.ONE_ETH_IN_WEI,
ethereumConnection: this.ethereumConnection
Expand Down
42 changes: 35 additions & 7 deletions src/Exchange.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import BigNumber from "bignumber.js";
import BN from "bn.js";
import { Exchange as ExchangeInstance } from "../generated/index";
import { TransactionObject } from "../generated/types/types";
import { AbstractContract } from "./AbstractContract";
import { CHUNK_SIZE, LEGACY_CONTRACTS_CHUNK_SIZE, ONE_ETH_IN_WEI, PPM_DIV } from "./constants";
import { AugmintToken } from "./AugmintToken";
import { CHUNK_SIZE, DECIMALS, DECIMALS_DIV, LEGACY_CONTRACTS_CHUNK_SIZE, ONE_ETH_IN_WEI, PPM_DIV } from "./constants";
import { EthereumConnection } from "./EthereumConnection";
import { MATCH_MULTIPLE_ADDITIONAL_MATCH_GAS, MATCH_MULTIPLE_FIRST_MATCH_GAS } from "./gas";
import { MATCH_MULTIPLE_ADDITIONAL_MATCH_GAS, MATCH_MULTIPLE_FIRST_MATCH_GAS, PLACE_ORDER_GAS } from "./gas";
import { Rates } from "./Rates";
import { Transaction } from "./Transaction";

Expand Down Expand Up @@ -50,9 +52,8 @@ interface ISellOrderCalc extends ISellOrder {
}

interface IExchangeOptions {
peggedSymbol: Promise<string>;
token: AugmintToken;
rates: Rates;
decimalsDiv: Promise<number>;
ONE_ETH_IN_WEI: number;
ethereumConnection: EthereumConnection;
}
Expand All @@ -67,6 +68,7 @@ export class Exchange extends AbstractContract {
private web3: any;
private safeBlockGasLimit: number;
/** fiat symbol this exchange is linked to (via Exchange.augmintToken) */
private token: AugmintToken;
private tokenPeggedSymbol: Promise<string>;
private rates: Rates;
private decimalsDiv: Promise<number>;
Expand All @@ -79,9 +81,8 @@ export class Exchange extends AbstractContract {
this.ethereumConnection = options.ethereumConnection;
this.web3 = this.ethereumConnection.web3;
this.safeBlockGasLimit = this.ethereumConnection.safeBlockGasLimit;
this.tokenPeggedSymbol = options.peggedSymbol;
this.rates = options.rates;
this.decimalsDiv = options.decimalsDiv;
this.token = options.token;
this.ONE_ETH_IN_WEI = options.ONE_ETH_IN_WEI;
}

Expand Down Expand Up @@ -145,7 +146,7 @@ export class Exchange extends AbstractContract {

public async getOrders(orderDirection: OrderDirection, offset: number): Promise<IOrderBook> {
const blockGasLimit: number = this.safeBlockGasLimit;
const decimalsDiv = await this.decimalsDiv;
const decimalsDiv = await this.token.decimalsDiv;
// @ts-ignore TODO: remove ts-ignore and handle properly when legacy contract support added
const isLegacyExchangeContract: boolean = typeof this.instance.methods.CHUNK_SIZE === "function";
const chunkSize: number = isLegacyExchangeContract ? LEGACY_CONTRACTS_CHUNK_SIZE : CHUNK_SIZE;
Expand Down Expand Up @@ -202,6 +203,33 @@ export class Exchange extends AbstractContract {
return orders;
}

public placeSellTokenOrder(price: BN, amount: BN): Transaction {
const web3Tx: TransactionObject<void> = this.token.instance.methods.transferAndNotify(
this.address,
amount.toString(),
price.toString()
);

const transaction: Transaction = new Transaction(this.ethereumConnection, web3Tx, {
gasLimit: PLACE_ORDER_GAS,
to: this.address
});

return transaction;
}

public placeBuyTokenOrder(price: BN, amount: BN): Transaction {
const web3Tx: TransactionObject<string> = this.instance.methods.placeBuyTokenOrder(price.toString());

const transaction: Transaction = new Transaction(this.ethereumConnection, web3Tx, {
gasLimit: PLACE_ORDER_GAS,
to: this.address,
value: amount
});

return transaction;
}

public isOrderBetter(o1: IGenericOrder, o2: IGenericOrder): number {
if (o1.direction !== o2.direction) {
throw new Error("isOrderBetter(): order directions must be the same" + o1 + o2);
Expand Down
2 changes: 2 additions & 0 deletions src/Transaction.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BN } from "bn.js";
import { EventEmitter } from "events";
import PromiEvent from "web3-core-promievent";
import { TransactionObject } from "../generated/types/types";
Expand All @@ -10,6 +11,7 @@ interface ISendOptions {
gasLimit?: number;
gasPrice?: number;
nonce?: number;
value?: BN;
}

interface ITxToSign extends ISendOptions {
Expand Down
4 changes: 0 additions & 4 deletions test/Exchange.Matching.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ function getBnPrice(price) {
return new BigNumber((price * PPM_DIV).toFixed(0));
}

describe("getMatchMultipleOrdersTx", () => {
it("should match orders on chain");
});

describe("calculateMatchingOrders", () => {
const ETHEUR_RATE = new BigNumber(50000);
const BN_ONE = new BigNumber(1);
Expand Down
134 changes: 134 additions & 0 deletions test/Exchange.orders.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
const { BN } = require("bn.js");
const { assert } = require("chai");
const { takeSnapshot, revertSnapshot } = require("./testHelpers/ganache.js");
const { Augmint, utils } = require("../dist/index.js");
const { assertEvent } = require("./testHelpers/events");
const { issueToken } = require("./testHelpers/token");
const { TransactionSendError } = Augmint.Errors;
const loadEnv = require("./testHelpers/loadEnv.js");
const config = loadEnv();
if (config.LOG) {
utils.logger.level = config.LOG;
}

describe("place orders - invalid args", () => {
let augmint = null;
let exchange = null;

before(async () => {
augmint = await Augmint.create(config);
exchange = augmint.exchange;
});

it("placeBuyTokenOrder should allow only integer for price", () => {
assert.throws(
() => exchange.placeBuyTokenOrder(1.1, 10000).send({ from: augmint.ethereumConnection.accounts[0] }),
TransactionSendError,
/invalid number value/
);
});

it("placeSellTokenOrder should allow only integer for price", () => {
assert.throws(
() => exchange.placeSellTokenOrder(1.1, 10000).send({ from: augmint.ethereumConnection.accounts[0] }),
TransactionSendError,
/invalid number value/
);
});

it("placeSellTokenOrder should allow only integer for tokenamount", () => {
assert.throws(
() => exchange.placeSellTokenOrder(1000000, 100.121).send({ from: augmint.ethereumConnection.accounts[0] }),
TransactionSendError,
/invalid number value/
);
});
});

describe("place orders - onchain", () => {
let augmint = null;
let exchange = null;
let accounts;
let snapshotId;

beforeEach(async () => {
snapshotId = await takeSnapshot(augmint.ethereumConnection.web3);
});

afterEach(async () => {
await revertSnapshot(augmint.ethereumConnection.web3, snapshotId);
});

before(async () => {
augmint = await Augmint.create(config);
exchange = augmint.exchange;
accounts = augmint.ethereumConnection.accounts;
});

it("placeBuyTokenOrder success", async () => {
const maker = accounts[1];
const price = new BN(1.01 * Augmint.constants.PPM_DIV);
const amount = new BN(2000000000);
const tx = exchange.placeBuyTokenOrder(price, amount);
const txReceipt = await tx.send({ from: maker }).getTxReceipt();

assert(txReceipt.status);
// event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);
await assertEvent(exchange.instance, "NewOrder", {
orderId: x => parseInt(x),
maker: maker,
price: price.toString(),
tokenAmount: "0",
weiAmount: amount.toString()
});
});

it("placeSellTokenOrder success", async () => {
const maker = accounts[1];
const price = new BN(1.02 * Augmint.constants.PPM_DIV);
const amount = new BN(1099);

await issueToken(augmint, accounts[0], maker, amount);

const tx = exchange.placeSellTokenOrder(price, amount);
const txReceipt = await tx.send({ from: maker }).getTxReceipt();

assert(txReceipt.status);

// event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);
await assertEvent(exchange.instance, "NewOrder", {
orderId: x => parseInt(x),
maker: maker,
price: price.toString(),
tokenAmount: amount.toString(),
weiAmount: "0"
});
});
});

describe("cancel order ", () => {
let augmint = null;
let exchange = null;
let snapshotId;

before(async () => {
augmint = await Augmint.create(config);
exchange = augmint.exchange;
});

beforeEach(async () => {
snapshotId = await takeSnapshot(augmint.ethereumConnection.web3);
});

afterEach(async () => {
await revertSnapshot(augmint.ethereumConnection.web3, snapshotId);
});

it("should cancel a buy order");

it("should cancel a sell order");

it("cancel sell order should throw if order id is invalid");

it("cancel buy order should throw if order id is invalid");
});
2 changes: 1 addition & 1 deletion test/Exchange.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe("getOrderBook", () => {

describe("isOrderBetter", () => {
let exchange = null;
before(async () => {
before(async () => {
const myAugmint = await Augmint.create(config);
exchange = myAugmint.exchange;
});
Expand Down
19 changes: 19 additions & 0 deletions test/testHelpers/token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { mine } = require("./ganache.js");

module.exports = { issueToken };

async function issueToken(augmint, sender, to, _amount) {
const amount = (_amount * (await augmint.token.decimalsDiv)).toString();
const MONETARYSUPERVISOR_PERMISSION = augmint.ethereumConnection.web3.utils.asciiToHex("MonetarySupervisor");
const token = (await augmint.token).instance;
const web3 = augmint.ethereumConnection.web3;

token.methods.grantPermission(sender, MONETARYSUPERVISOR_PERMISSION).send({ from: sender });
await mine(web3, 1); // we mine instead of waiting for blockTimeout to mine in ganache to speed up tests

token.methods.issueTo(to, amount).send({ from: sender });
await mine(web3, 1);

token.methods.revokePermission(sender, MONETARYSUPERVISOR_PERMISSION).send({ from: sender });
await mine(web3, 1);
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU=

bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.4.0:
bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
Expand Down