Skip to content

Commit

Permalink
Add handling of hops input to transfer, updateTransitiveTransfer and …
Browse files Browse the repository at this point in the history
…findTransitiveTransfer (#153)

* Add handling of hops input to findTransitiveTransfer

* Add hops to updateTransitiveTransfer

* Add hops to transfer

* Add and edit tests for transfer hops parameter

* Fix tests for transfer hops parameter

* Reorder tests

* Fix updateTransitiveTransfer api call

* Add documentation for methods

Co-authored-by: llunaCreixent <[email protected]>
  • Loading branch information
louilinn and llunaCreixent authored Jan 23, 2023
1 parent fa4aef0 commit b661de2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const MAX_TRANSFER_STEPS = 52;
* @param {string} userOptions.from - sender Safe address
* @param {string} userOptions.to - receiver Safe address
* @param {BN} userOptions.value - value of Circles tokens
* @param {number} userOptions.hops - maximum number of trust hops away from them sending user inside the trust network for finding transaction steps
*
* @return {Object[]} - transaction steps
*/
Expand All @@ -38,6 +39,10 @@ export async function findTransitiveTransfer(web3, utils, userOptions) {
value: {
type: web3.utils.isBN,
},
hops: {
type: 'number',
default: 3,
},
});

try {
Expand All @@ -48,6 +53,7 @@ export async function findTransitiveTransfer(web3, utils, userOptions) {
from: options.from,
to: options.to,
value: options.value.toString(),
hops: options.hops.toString(),
},
});

Expand All @@ -69,6 +75,7 @@ export async function findTransitiveTransfer(web3, utils, userOptions) {
* @param {string} userOptions.from - sender Safe address
* @param {string} userOptions.to - receiver Safe address
* @param {BN} userOptions.value - value of Circles tokens
* @param {number} userOptions.hops - maximum number of trust hops away from them sending user inside the trust network for finding transaction steps
*
* @return {boolean} - steps are updated
*/
Expand All @@ -83,6 +90,10 @@ export async function updateTransitiveTransfer(web3, utils, userOptions) {
value: {
type: web3.utils.isBN,
},
hops: {
type: 'number',
default: 3,
},
});

try {
Expand All @@ -93,6 +104,7 @@ export async function updateTransitiveTransfer(web3, utils, userOptions) {
from: options.from,
to: options.to,
value: options.value.toString(),
hops: options.hops.toString(),
},
});

Expand Down Expand Up @@ -351,6 +363,7 @@ export default function createTokenModule(web3, contracts, utils) {
* @param {string} userOptions.from - sender Safe address
* @param {string} userOptions.to - receiver Safe address
* @param {BN} userOptions.value - value for transactions path
* @param {number} userOptions.hops - maximum number of trust hops away from them sending user inside the trust network for finding transaction steps
*
* @return {boolean} - steps are updated
*/
Expand All @@ -370,6 +383,7 @@ export default function createTokenModule(web3, contracts, utils) {
* @param {string} userOptions.to - receiver address
* @param {BN} userOptions.value - value
* @param {string} userOptions.paymentNote - optional payment note stored in API
* @param {number} userOptions.hops - maximum number of trust hops away from them sending user inside the trust network for finding transaction steps
*
* @return {string} - transaction hash
*/
Expand All @@ -390,6 +404,10 @@ export default function createTokenModule(web3, contracts, utils) {
type: 'string',
default: '',
},
hops: {
type: 'number',
default: 3,
},
});

const transfer = {
Expand Down
58 changes: 56 additions & 2 deletions test/token.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,48 @@ describe('Token', () => {
// actually is (25).
expect(result.maxFlowValue).toBe(core.utils.toFreckles(1));
});

it('should return max flow and possible path when using hops parameter', async () => {
const value = new web3.utils.BN(core.utils.toFreckles(1));

const result = await core.token.findTransitiveTransfer(accounts[0], {
from: safeAddresses[0],
to: safeAddresses[4],
value,
hops: 2,
});
expect(result.transferSteps.length).toBe(2);
expect(result.transferSteps[0].from).toBe(safeAddresses[0]);
expect(result.transferSteps[0].to).toBe(safeAddresses[3]);
expect(result.transferSteps[0].value).toBe(core.utils.toFreckles(1));
expect(result.transferSteps[0].tokenOwnerAddress).toBe(safeAddresses[0]);
expect(result.transferSteps[1].from).toBe(safeAddresses[3]);
expect(result.transferSteps[1].to).toBe(safeAddresses[4]);
expect(result.transferSteps[1].value).toBe(core.utils.toFreckles(1));
expect(result.transferSteps[1].tokenOwnerAddress).toBe(safeAddresses[3]);

// The `pathfinder` stops searching for max flow as soon as it found a
// successful solution, therefore it returns a lower max flow than it
// actually is (25).
expect(result.maxFlowValue).toBe(core.utils.toFreckles(1));
});

it('should return 0 max flow and no path when using too low hops parameter', async () => {
const value = new web3.utils.BN(core.utils.toFreckles(1));

const result = await core.token.findTransitiveTransfer(accounts[0], {
from: safeAddresses[0],
to: safeAddresses[4],
value,
hops: 1,
});
expect(result.transferSteps.length).toBe(0);

// The `pathfinder` stops searching for max flow as soon as it found a
// successful solution, therefore it returns a lower max flow than it
// actually is (25).
expect(result.maxFlowValue).toBe(core.utils.toFreckles(0));
});
});

describe('Transitive Transactions', () => {
Expand Down Expand Up @@ -266,16 +308,17 @@ describe('Token', () => {
);
});

it('should fail sending Circles when there is no path', async () => {
// Max flow is smaller than the given transfer value
it('should fail sending Circles when maxflow is lower than requested transfer value', async () => {
await expect(
core.token.transfer(accounts[0], {
from: safeAddresses[0],
to: safeAddresses[4],
value: web3.utils.toBN(core.utils.toFreckles('100')),
}),
).rejects.toThrow();
});

it('should fail sending Circles when there is no trust path between sender and receiver', async () => {
// Trust connection does not exist between node 0 and 5
await expect(
core.token.transfer(accounts[0], {
Expand All @@ -286,6 +329,17 @@ describe('Token', () => {
).rejects.toThrow();
});

it('should fail to send Circles to someone transitively if hops are too few to find a path', async () => {
await expect(
core.token.transfer(accounts[0], {
from: safeAddresses[0],
to: safeAddresses[4],
value: web3.utils.toBN(core.utils.toFreckles(5)),
hops: 1,
}),
).rejects.toThrow();
});

it('should fail sending Circles when data error', async () => {
// Update the edges.csv file simulating data error:
// Direct path does not exist between safeAddress 0 and 4,
Expand Down

0 comments on commit b661de2

Please sign in to comment.