Skip to content
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# set-protocol-utils

Common util methods used when interacting with setProtocol.js or our Set Protocol smart contracts
Common util methods used when interacting with setProtocol.js or our Set Protocol smart contracts
<a href='https://www.npmjs.com/package/set-protocol-contracts'>
<img src='https://img.shields.io/npm/v/set-protocol-utils.svg' alt='NPM' />
</a>
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
},
"homepage": "https://github.com/SetProtocol/set-protocol-utils#readme",
"devDependencies": {
"@0xproject/typescript-typings": "^0.0.3",
"@0xproject/types": "^1.0.1-rc.3",
"@0xproject/typescript-typings": "^1.0.3",
"@types/lodash": "4.14.104",
"abi-decoder": "^1.0.9",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"typedoc": "^0.11.1",
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/base-contract": "^1.0.4",
"@0xproject/order-utils": "^1.0.1-rc.2",
"@0xproject/web3-wrapper": "^1.1.2",
"@types/node": "^8.0.53",
"bignumber.js": "~4.1.0",
"ethereum-types": "^1.0.0",
Expand Down
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { BigNumber } from 'bignumber.js';


export const constants = {
EXCHANGES: {
ZERO_EX: 1,
KYBER: 2,
TAKER_WALLET: 3,
},
MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
ZERO: new BigNumber(0),
ZERO_EX_SNAPSHOT_EXCHANGE_ADDRESS: '0x48bacb9266a570d521063ef5dd96e61686dbe788',
ZERO_EX_SNAPSHOT_ERC20_PROXY_ADDRESS: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
};
54 changes: 53 additions & 1 deletion src/encoding.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import * as _ from 'lodash';
import * as ethUtil from 'ethereumjs-util';
import * as Web3 from 'web3';
import { BigNumber } from 'bignumber.js';

import { Bytes32 } from './types';
import { Bytes, Bytes32 } from './types';

const web3 = new Web3();


export function concatBytes(inputs: Bytes[]): Bytes {
if (inputs.length === 0) {
throw new Error('No errors in concat Orders');
}

let bytes: Bytes = '';
_.each(inputs, input => {
bytes = bytes.concat(removeHexPrefix(input));
});

return addHexPrefix(bytes);
}

export function bufferArrayToHex(bufferArray: Buffer[]): Bytes32 {
const buffer = Buffer.concat(bufferArray);

Expand All @@ -17,6 +31,20 @@ export function bufferObjectWithProperties(types: string[], values: any[]): Buff
return ethUtil.sha3(solidityPack(types, values));
}

export function numBytesFromBuffer(buffer: Buffer[]): BigNumber {
const hex = bufferArrayToHex(buffer);

return numBytesFromHex(hex);
}

export function numBytesFromHex(hex: string): BigNumber {
if (!isHexPrefixed(hex)) {
throw new Error(`${hex} is not a hex string. It must be Hex-Prefixed`);
}

return new BigNumber(removeHexPrefix(hex).length).div(2);
}

export function paddedBufferForPrimitive(input: any): Buffer {
return ethUtil.setLengthLeft(ethUtil.toBuffer(input), 32);
}
Expand All @@ -40,6 +68,14 @@ function elementaryName (
return name;
}

function isHexPrefixed(str: any): boolean {
if (typeof str !== 'string') {
throw new Error("Must be type 'string', is currently type " + (typeof str) + ', while checking isHexPrefixed.');
}

return str.slice(0, 2) === '0x';
}

// Parse N from type<N>
function parseTypeN (
type: string,
Expand All @@ -62,6 +98,22 @@ function parseNumber (
}
}

function removeHexPrefix(input: any): string {
if (typeof input !== 'string') {
return input;
}

return isHexPrefixed(input) ? input.slice(2) : input;
}

function addHexPrefix(input: any): string {
if (typeof input !== 'string') {
return input;
}

return !isHexPrefixed(input) ? `0x${input}` : input;
}

function solidityPack (
types: string[],
values: any[],
Expand Down
87 changes: 86 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { BigNumber } from 'bignumber.js';
import { Order } from '@0xproject/types';
import * as Web3 from 'web3';

import { Address, Bytes32, IssuanceOrder, Log, ECSig } from './types';
import { Address, Bytes, Bytes32, IssuanceOrder, Log, ECSig } from './types';
import { constants } from './constants';
import {
bufferArrayToHex,
concatBytes,
numBytesFromBuffer,
paddedBufferForBigNumber,
paddedBufferForPrimitive,
} from './encoding';
Expand All @@ -20,6 +23,12 @@ import {
parseSignatureHexAsRSV,
signMessage
} from './signing';
import {
encodeZeroExOrder,
generateZeroExExchangeWrapperOrder,
generateZeroExOrder,
signZeroExOrderAsync,
} from './zeroEx';


/**
Expand Down Expand Up @@ -52,6 +61,24 @@ export class SetProtocolUtils {
return bufferArrayToHex(bufferArray);
}

/**
* Converts an array of Bytes (each prefixed 0x) into one byte array
* @param bytes Array of byte strings
* @return A single byte string representing the array of bytes
*/
public static concatBytes(bytes: Bytes[]): Bytes {
return concatBytes(bytes);
}

/**
* Converts a 0x order into binary representation, often to get byte count
* @param order Object conforming to 0x's Order inteface
* @return Array of buffers representing the order
*/
public static encodeZeroExOrder(order: Order): Buffer[] {
return encodeZeroExOrder(order);
}

/**
* Generates expiration timestamp that can be used as part of IssuanceOrder
* @param minutes Number of minutes from now
Expand All @@ -69,6 +96,36 @@ export class SetProtocolUtils {
return generateSalt();
}

/**
* Generates a byte array with a valid 0x order that can be passed into ZeroExExchangeWrapper
* @param order Object conforming to 0x's Order inteface
* @param signature Elliptic curve signature as hex string
* @param fillAmount Amount of 0x order to fill
* @return Hex string representation of valid 0xExchangeWrapper order
*/
public static generateZeroExExchangeWrapperOrder(order: Order, signature: Bytes, fillAmount: BigNumber): Bytes {
return generateZeroExExchangeWrapperOrder(order, signature, fillAmount);
}

/**
* Generates a 0x order
* @param makerAddress Maker token owner
* @param makerToken Asset to exchange
* @param takerToken Asset to exchange for
* @param makerAssetAmount Amount of asset to exchange
* @param takerAssetAmount Amount of asset to exchange for
* @return Object conforming to 0x's Order inteface
*/
public static generateZeroExOrder(
makerAddress: Address,
makerToken: Address,
takerToken: Address,
makerAssetAmount: BigNumber,
takerAssetAmount: BigNumber,
): Order {
return generateZeroExOrder(makerAddress, makerToken, takerToken, makerAssetAmount, takerAssetAmount);
}

/**
* Converts an IssuanceOrder into hex
* @param order An object adhering to the IssuanceOrder interface
Expand All @@ -78,6 +135,15 @@ export class SetProtocolUtils {
return hashOrderHex(order);
}

/**
* Gets the length of a buffer's contents
* @param buffer A buffer of arbitray length
* @return Number of bytes in hex representation of the buffer
*/
public static numBytesFromBuffer(buffer: Buffer[]): BigNumber {
return numBytesFromBuffer(buffer);
}

/**
* Generates a buffer for a primitive value padded to 32 bytes. Use for encoding addresses (string),
* enum, etc. Use paddedBufferForBigNumber for token amounts that need to be expressed in high numbers
Expand Down Expand Up @@ -115,6 +181,15 @@ export class SetProtocolUtils {
public async signMessage(message: string, address: Address): Promise<ECSig> {
return signMessage(this.web3, message, address);
}

/**
* Adds correct signature '0x' and signs 0x order
* @param order Object conforming to 0x's Order inteface
* @return Hex string representation of 0x 0rder signature
*/
public async signZeroExOrderAsync(order: Order): Promise<string> {
return signZeroExOrderAsync(order);
}
}


Expand All @@ -125,6 +200,16 @@ export class SetProtocolUtils {
export class SetProtocolTestUtils {
private web3: Web3;

/**
* Address of 0x exchange address contract on test rpc, loaded from snapshot
*/
public static ZERO_EX_EXCHANGE_ADDRESS = constants.ZERO_EX_SNAPSHOT_EXCHANGE_ADDRESS;

/**
* Address of 0x erc20 proxy contract on test rpc, loaded from snapshot
*/
public static ZERO_EX_ERC20_PROXY_ADDRESS = constants.ZERO_EX_SNAPSHOT_ERC20_PROXY_ADDRESS;

/**
* Initialize a TestUtils class
* @param web3 Web3 instance to use
Expand Down
1 change: 1 addition & 0 deletions src/signing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Web3 from 'web3';

import { Address, ECSig } from './types';


export function parseSignatureHexAsRSV(signatureHex: string): ECSig {
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);

Expand Down
12 changes: 6 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ export type Bytes32 = string;
export type Bytes = string;
export type UInt = number | BigNumber;

export interface ECSig {
v: UInt;
r: string;
s: string;
}

export interface IssuanceOrder {
setAddress: Address;
makerAddress: Address;
Expand All @@ -21,12 +27,6 @@ export interface IssuanceOrder {
requiredComponentAmounts: BigNumber[];
}

export interface ECSig {
v: UInt;
r: string;
s: string;
}

export interface Log {
event: string;
address: Address;
Expand Down
Loading