Skip to content

Commit

Permalink
Merge pull request #92 from CityOfZion/CU-86drvz6jc-4
Browse files Browse the repository at this point in the history
CU-86drvz6jc Swap Multi Invoke - Implement routes definitions to Swap…
  • Loading branch information
raulduartep authored Aug 22, 2024
2 parents f9c090e + 420d03a commit 939887a
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@cityofzion/bs-neo3",
"comment": "Fixing NEO implementation",
"type": "patch"
}
],
"packageName": "@cityofzion/bs-neo3"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { Network, SwapServiceSwapToReceiveArgs, SwapServiceSwapToUseArgs } from '@cityofzion/blockchain-service'
import { ContractInvocationMulti } from '@cityofzion/neon-dappkit-types'
import { FlamingoSwapInvocationBuilderNeo3 } from '../../../builder/invocation/FlamingoSwapInvocationBuilderNeo3'
import { FlamingoSwapConstants } from '../../../constants/FlamingoSwapConstants'
import { BSNeo3Helper, BSNeo3NetworkId } from '../../../helpers/BSNeo3Helper'

let network: Network<BSNeo3NetworkId>

describe('FlamingoSwapInvocationBuilderNeo3', () => {
beforeEach(() => {
network = BSNeo3Helper.DEFAULT_NETWORK
})

it('Should match the invocation script swapping NEO to GAS - swapTokenToUse', () => {
const NEO = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['NEO']
const bNEO = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['bNEO']
const GAS = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['GAS']

const data: SwapServiceSwapToUseArgs<BSNeo3NetworkId> = {
address: 'address',
amountToUse: '2',
deadline: '10',
minimumReceived: '5.98684835',
network,
routePath: [NEO, bNEO, GAS],
type: 'swapTokenToUse',
}

const response = FlamingoSwapInvocationBuilderNeo3.swapInvocation(data)

const expectedResponse: ContractInvocationMulti = {
invocations: [
{
scriptHash: '0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5',
operation: 'transfer',
args: [
{
type: 'Hash160',
value: data.address,
},
{
type: 'Hash160',
value: '0x48c40d4666f93408be1bef038b6722404d9a4c2a',
},
{
type: 'Integer',
value: '2',
},
{
type: 'Any',
value: null,
},
],
},
{
scriptHash: '0xf970f4ccecd765b63732b821775dc38c25d74f23',
operation: 'swapTokenInForTokenOut',
args: [
{
type: 'Hash160',
value: data.address,
},
{
type: 'Integer',
value: '200000000',
},
{
type: 'Integer',
value: '598684835',
},
{
type: 'Array',
value: [
{
type: 'Hash160',
value: '0x48c40d4666f93408be1bef038b6722404d9a4c2a',
},
{
type: 'Hash160',
value: '0xd2a4cff31913016155e38e474a2c06d08be276cf',
},
],
},
{
type: 'Integer',
value: expect.any(String),
},
],
},
],
signers: [
{
scopes: 16,
allowedContracts: [
'0x3244fcadcccff190c329f7b3083e4da2af60fbce',
'0xf970f4ccecd765b63732b821775dc38c25d74f23',
'0xca2d20610d7982ebe0bed124ee7e9b2d580a6efc',
'0xfb75a5314069b56e136713d38477f647a13991b4',
'0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5',
'0x48c40d4666f93408be1bef038b6722404d9a4c2a',
'0xd2a4cff31913016155e38e474a2c06d08be276cf',
],
},
],
}

expect(response).toEqual(expectedResponse)
})

it('Should match the invocation script swapping GAS to NEO - swapTokenToReceive', () => {
const NEO = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['NEO']
const bNEO = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['bNEO']
const GAS = FlamingoSwapConstants.FLAMINGO_SWAP_TOKENS[network.id]['GAS']

const data: SwapServiceSwapToReceiveArgs<BSNeo3NetworkId> = {
address: 'address',
amountToReceive: '1',
deadline: '10',
maximumSelling: '3.04188283',
network,
routePath: [GAS, bNEO, NEO],
type: 'swapTokenToReceive',
}

const response = FlamingoSwapInvocationBuilderNeo3.swapInvocation(data)

const expectedResponse: ContractInvocationMulti = {
invocations: [
{
scriptHash: '0xf970f4ccecd765b63732b821775dc38c25d74f23',
operation: 'swapTokenOutForTokenIn',
args: [
{
type: 'Hash160',
value: data.address,
},
{
type: 'Integer',
value: '100000000',
},
{
type: 'Integer',
value: '304188283',
},
{
type: 'Array',
value: [
{
type: 'Hash160',
value: '0xd2a4cff31913016155e38e474a2c06d08be276cf',
},
{
type: 'Hash160',
value: '0x48c40d4666f93408be1bef038b6722404d9a4c2a',
},
],
},
{
type: 'Integer',
value: expect.any(String),
},
],
},
{
scriptHash: '0xd2a4cff31913016155e38e474a2c06d08be276cf',
operation: 'transfer',
args: [
{
type: 'Hash160',
value: data.address,
},
{
type: 'Hash160',
value: '0x48c40d4666f93408be1bef038b6722404d9a4c2a',
},
{
type: 'Integer',
value: '100000',
},
{
type: 'Any',
value: null,
},
],
},
],
signers: [
{
scopes: 16,
allowedContracts: [
'0xf970f4ccecd765b63732b821775dc38c25d74f23',
'0xca2d20610d7982ebe0bed124ee7e9b2d580a6efc',
'0xfb75a5314069b56e136713d38477f647a13991b4',
'0xd2a4cff31913016155e38e474a2c06d08be276cf',
'0x48c40d4666f93408be1bef038b6722404d9a4c2a',
'0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5',
'0x3244fcadcccff190c329f7b3083e4da2af60fbce',
],
},
],
}

expect(response).toEqual(expectedResponse)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ export class FlamingoSwapInvocationBuilderNeo3 {
const tokenToReceive = routePath[routePath.length - 1]

const scriptHashes = FlamingoSwapHelper.getFlamingoSwapScriptHashes(network)
const tokenToReceiveOverrode = FlamingoSwapHelper.overrideToken(network, tokenToReceive)

const invocations: ContractInvocation[] = []
const allowedContracts = this.#getAllowedContracts(scriptHashes, routePath)
const allowedContracts: string[] = []

const tokenToReceiveOverrode = FlamingoSwapHelper.overrideToken(network, tokenToReceive)
const routePathOverrode = FlamingoSwapHelper.overrideRoutePath(network, routePath)

const amountToReceiveFormatted = FlamingoSwapHelper.formatAmount(amountToReceive, tokenToReceiveOverrode.decimals)
const maximumSellingFormatted = FlamingoSwapHelper.formatAmount(maximumSelling, tokenToUse.decimals)
Expand All @@ -41,19 +43,22 @@ export class FlamingoSwapInvocationBuilderNeo3 {
amountToReceive: amountToReceiveFormatted,
maximumSelling: maximumSellingFormatted,
deadline,
args: this.#mapRoutePathToArgs(routePath),
args: this.#mapRoutePathToArgs(routePathOverrode),
})

invocations.push(swapInvocation)
allowedContracts.push(...this.#getAllowedContracts(scriptHashes, routePath))

if (FlamingoSwapHelper.isNeoToken(network, tokenToReceive)) {
const amountToReceiveTransfer = u.BigInteger.fromNumber(
Number(amountToReceiveFormatted) * FlamingoSwapConstants.GAS_PER_NEO
).toString()

const neoTransferInvocation = this.#buildNEOTransferInvocation(address, amountToReceiveTransfer, network)
const gasHash = FlamingoSwapHelper.getFlamingoSwapToken(network, 'GAS').hash
const neoTransferInvocation = this.#buildNEOTransferInvocation(address, gasHash, amountToReceiveTransfer, network)

invocations.push(neoTransferInvocation)
allowedContracts.push(FlamingoSwapHelper.getFlamingoSwapPool(network, 'FLP-bNEO-GAS').hash)
}

return {
Expand All @@ -76,15 +81,20 @@ export class FlamingoSwapInvocationBuilderNeo3 {
const scriptHashes = FlamingoSwapHelper.getFlamingoSwapScriptHashes(network)

const invocations: ContractInvocation[] = []
const allowedContracts = this.#getAllowedContracts(scriptHashes, routePath)
const allowedContracts: string[] = []

if (FlamingoSwapHelper.isNeoToken(network, tokenToUse)) {
const neoTransferInvocation = this.#buildNEOTransferInvocation(address, amountToUse, network)
const neoHash = FlamingoSwapHelper.getFlamingoSwapToken(network, 'NEO').hash
const neoTransferInvocation = this.#buildNEOTransferInvocation(address, neoHash, amountToUse, network)

invocations.push(neoTransferInvocation)
allowedContracts.push(FlamingoSwapHelper.getFlamingoSwapPool(network, 'FLP-bNEO-GAS').hash)
}

const amountToUseFormatted = FlamingoSwapHelper.formatAmount(amountToUse, tokenToUse.decimals)
const tokenToUseOverrode = FlamingoSwapHelper.overrideToken(network, tokenToUse)
const routePathOverrode = FlamingoSwapHelper.overrideRoutePath(network, routePath)

const amountToUseFormatted = FlamingoSwapHelper.formatAmount(amountToUse, tokenToUseOverrode.decimals)
const minimumReceivedFormatted = FlamingoSwapHelper.formatAmount(minimumReceived, tokenToReceive.decimals)

const swapInvocation = NeonDappKitInvocationBuilderNeo3.swapTokenInForTokenOutContractInvocation({
Expand All @@ -93,10 +103,11 @@ export class FlamingoSwapInvocationBuilderNeo3 {
minimumReceived: minimumReceivedFormatted,
senderAddress: address,
deadline,
args: this.#mapRoutePathToArgs(routePath),
args: this.#mapRoutePathToArgs(routePathOverrode),
})

invocations.push(swapInvocation)
allowedContracts.push(...this.#getAllowedContracts(scriptHashes, routePath))

return {
invocations,
Expand All @@ -120,15 +131,19 @@ export class FlamingoSwapInvocationBuilderNeo3 {
]
}

static #buildNEOTransferInvocation(address: string, amount: string, network: Network): ContractInvocation {
static #buildNEOTransferInvocation(
senderAddress: string,
contractHash: string,
amount: string,
network: Network
): ContractInvocation {
const bNEO = FlamingoSwapHelper.getFlamingoSwapToken(network, 'bNEO')
const GAS = FlamingoSwapHelper.getFlamingoSwapToken(network, 'GAS')

return NeonDappKitInvocationBuilderNeo3.transferContractInvocation({
senderAddress: address,
amount,
contractHash,
tokenHash: bNEO.hash,
contractHash: GAS.hash,
senderAddress,
amount,
})
}
}
6 changes: 6 additions & 0 deletions packages/bs-neo3/src/helpers/FlamingoSwapHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ export class FlamingoSwapHelper {
return overrodeRoute
}

static overrideRoutePath(network: Network<BSNeo3NetworkId>, routePath: Token[]): Token[] {
const overrodeRoutePath = routePath.map(token => this.overrideToken(network, token))

return overrodeRoutePath.filter((item, index, arr) => arr.indexOf(item) === index)
}

static normalizeHash(hash: string): string {
return hash.startsWith('0x') ? hash.slice(2) : hash
}
Expand Down

0 comments on commit 939887a

Please sign in to comment.