Skip to content

Escrow contract integration #1910

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

Merged
merged 34 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e9a663f
Created Escrow contract class.
mariacarmina Feb 3, 2025
c07cd43
Fix workflow.
mariacarmina Feb 4, 2025
4b1c8b0
Added test with deposit and withdrw funds.
mariacarmina Feb 18, 2025
f755676
Use barge with escrow contracts.
mariacarmina Feb 19, 2025
1b0eee1
use barge main branch.
mariacarmina Feb 20, 2025
433a3de
Add docker logs.
mariacarmina Feb 20, 2025
6882b67
Update contracts in ci.
mariacarmina Feb 20, 2025
7822f64
Fix docker container.
mariacarmina Feb 20, 2025
50c18a3
export contracts version for barge.
mariacarmina Feb 20, 2025
f63051d
Changed contracts version.
mariacarmina Feb 21, 2025
0c9ec8c
debug.
mariacarmina Feb 21, 2025
49327bc
Add more logs.
mariacarmina Feb 21, 2025
5cd36a9
Fix spender.
mariacarmina Feb 21, 2025
b579ecd
Fix assert.
mariacarmina Feb 21, 2025
e49c6e4
Debug.
mariacarmina Feb 21, 2025
06329f8
debug.
mariacarmina Feb 21, 2025
8dfd0d6
JSON parse.
mariacarmina Feb 21, 2025
ca041b2
Fix extraction.
mariacarmina Feb 21, 2025
c75c465
Fix test.
mariacarmina Feb 21, 2025
3b4cc83
Authorize test.
mariacarmina Feb 21, 2025
fb09c6f
fix.
mariacarmina Feb 21, 2025
b8e23d9
fix return type.
mariacarmina Feb 21, 2025
69c7780
Merge branch 'main' into escrow-contract-integration
mariacarmina Mar 7, 2025
6f4238b
Fix conflicts.
mariacarmina Mar 11, 2025
9745736
Use the right version of contracts.
mariacarmina Mar 11, 2025
19a4451
Fix conflicts.
mariacarmina Mar 26, 2025
8d66e3d
update sdk and fix test
giurgiur99 Mar 26, 2025
aa62210
lint fix
giurgiur99 Mar 26, 2025
dda89da
Fix conflicts.
mariacarmina Apr 11, 2025
d68826f
Fix conflicts.
mariacarmina Apr 16, 2025
3632b7c
Update contracts version.
mariacarmina Apr 17, 2025
c82a0ce
Fix conflicts with main.
mariacarmina Apr 17, 2025
c983d60
Change contracts version.
mariacarmina Apr 17, 2025
d1eb26c
Fix conflicts.
mariacarmina Apr 28, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ jobs:
with:
repository: 'oceanprotocol/barge'
path: 'barge'

- name: Run Ganache with Barge
working-directory: ${{ github.workspace }}/barge
run: |
export CONTRACTS_VERSION=v2.3.0
bash -x start_ocean.sh --no-aquarius --no-elasticsearch --no-provider --no-dashboard 2>&1 > start_ocean.log &
- run: npm ci
- name: Wait for contracts deployment
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
"dependencies": {
"@oasisprotocol/sapphire-paratime": "^1.3.2",
"@oceanprotocol/contracts": "^2.2.0",
"@oceanprotocol/contracts": "^2.3.0",
"@oceanprotocol/ddo-js": "^0.0.8",
"@rdfjs/dataset": "^2.0.2",
"@rdfjs/formats-common": "^3.1.0",
Expand Down
167 changes: 167 additions & 0 deletions src/contracts/Escrow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { Signer } from 'ethers'
import Escrow from '@oceanprotocol/contracts/artifacts/contracts/escrow/Escrow.sol/Escrow.json'
import { amountToUnits, sendTx } from '../utils/ContractUtils'
import { AbiItem, ReceiptOrEstimate } from '../@types'
import { Config } from '../config'
import { SmartContractWithAddress } from './SmartContractWithAddress'

export class EscrowContract extends SmartContractWithAddress {
public abiEnterprise: AbiItem[]

getDefaultAbi() {
return Escrow.abi as AbiItem[]
}

/**
* Instantiate AccessList class
* @param {string} address The contract address.
* @param {Signer} signer The signer object.
* @param {string | number} [network] Network id or name
* @param {Config} [config] The configuration object.
* @param {AbiItem[]} [abi] ABI array of the smart contract
* @param {AbiItem[]} abiEnterprise Enterprise ABI array of the smart contract
*/
constructor(
address: string,
signer: Signer,
network?: string | number,
config?: Config,
abi?: AbiItem[]
) {
super(address, signer, network, config, abi)
this.abi = abi || this.getDefaultAbi()
}

/**
* Get Funds
* @return {Promise<any>} Funds
*/
public async getFunds(token: string): Promise<any> {
return await this.contract.getFunds(token)
}

/**
* Get User Funds
* @return {Promise<any>} User funds
*/
public async getUserFunds(payer: string, token: string): Promise<any> {
return await this.contract.getUserFunds(payer, token)
}

/**
* Get Locks
* @return {Promise<[]>} Locks
*/
public async getLocks(token: string, payer: string, payee: string): Promise<any[]> {
return await this.contract.getLocks(token, payer, payee)
}

/**
* Get Authorizations
* @return {Promise<[]>} Authorizations
*/
public async getAuthorizations(
token: string,
payer: string,
payee: string
): Promise<any[]> {
return await this.contract.getAuthorizations(token, payer, payee)
}

/**
* Deposit funds
* @param {String} token Token address
* @param {String} amount tokenURI
* @param {Boolean} estimateGas if True, return gas estimate
* @return {Promise<ReceiptOrEstimate>} returns the transaction receipt or the estimateGas value
*/
public async deposit<G extends boolean = false>(
token: string,
amount: string,
estimateGas?: G
): Promise<ReceiptOrEstimate<G>> {
const amountParsed = amountToUnits(null, null, amount, 18)
const estGas = await this.contract.estimateGas.deposit(token, amountParsed)
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
const trxReceipt = await sendTx(
estGas,
this.getSignerAccordingSdk(),
this.config?.gasFeeMultiplier,
this.contract.deposit,
token,
amountParsed
)
return <ReceiptOrEstimate<G>>trxReceipt
}

/**
* Withdraw funds
* @param {String[]} tokens Array of token addresses
* @param {String[]} amounts Array of token amounts
* @param {Boolean} estimateGas if True, return gas estimate
* @return {Promise<ReceiptOrEstimate>} returns the transaction receipt or the estimateGas value
*/
public async withdraw<G extends boolean = false>(
tokens: string[],
amounts: string[],
estimateGas?: G
): Promise<ReceiptOrEstimate<G>> {
const amountsParsed = amounts.map((amount) => amountToUnits(null, null, amount, 18))

const estGas = await this.contract.estimateGas.withdraw(tokens, amountsParsed)
if (estimateGas) return <ReceiptOrEstimate<G>>estGas

const trxReceipt = await sendTx(
estGas,
this.getSignerAccordingSdk(),
this.config?.gasFeeMultiplier,
this.contract.withdraw,
tokens,
amountsParsed
)
return <ReceiptOrEstimate<G>>trxReceipt
}

/**
* Authorize locks
* @param {String} token Token address
* @param {String} payee,
* @param {String} maxLockedAmount,
* @param {String} maxLockSeconds,
* @param {String} maxLockCounts,
* @param {Boolean} estimateGas if True, return gas estimate
* @return {Promise<ReceiptOrEstimate>} returns the transaction receipt or the estimateGas value
*/
public async authorize<G extends boolean = false>(
token: string,
payee: string,
maxLockedAmount: string,
maxLockSeconds: string,
maxLockCounts: string,
estimateGas?: G
): Promise<ReceiptOrEstimate<G>> {
const maxLockedAmountParsed = amountToUnits(null, null, maxLockedAmount, 18)
const maxLockSecondsParsed = amountToUnits(null, null, maxLockSeconds, 18)
const maxLockCountsParsed = amountToUnits(null, null, maxLockCounts, 18)
const estGas = await this.contract.estimateGas.authorize(
token,
payee,
maxLockedAmountParsed,
maxLockSecondsParsed,
maxLockCountsParsed
)
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
const trxReceipt = await sendTx(
estGas,
this.getSignerAccordingSdk(),
this.config?.gasFeeMultiplier,
this.contract.authorize,
token,
payee,
maxLockedAmountParsed,
maxLockSecondsParsed,
maxLockCountsParsed
)
return <ReceiptOrEstimate<G>>trxReceipt
}
}
99 changes: 99 additions & 0 deletions test/unit/Escrow.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { assert } from 'chai'
import { provider, getAddresses } from '../config'
import { BigNumber, Signer } from 'ethers'

import { Datatoken, amountToUnits, unitsToAmount } from '../../src/'
import { EscrowContract } from '../../src/contracts/Escrow'

describe('Escrow payments flow', () => {
let user1: Signer
let user2: Signer
let Escrow: EscrowContract
let datatoken: Datatoken
let addresses
let OCEAN

before(async () => {
user1 = (await provider.getSigner(3)) as Signer
user2 = (await provider.getSigner(4)) as Signer

addresses = await getAddresses()
OCEAN = addresses.Ocean
})

it('should initialize Escrow class', async () => {
Escrow = new EscrowContract(addresses.Escrow, user2, await user2.getChainId())
assert(Escrow !== null)
})

it('User2 makes a deposit in Escrow', async () => {
datatoken = new Datatoken(user2, await user2.getChainId())
const initialBalance = await datatoken.balance(OCEAN, await user2.getAddress())
const initialDepositedEscrow = await Escrow.getUserFunds(
await user2.getAddress(),
OCEAN
)
const initialDepositedEscrowAmount = await unitsToAmount(
null,
null,
initialDepositedEscrow[0].toString(),
18
)

await datatoken.approve(OCEAN, await user2.getAddress(), '1000')

await datatoken.transfer(OCEAN, await user2.getAddress(), '1000')

assert(
(await datatoken.balance(OCEAN, await user2.getAddress())) !==
`${initialBalance + 1000}`
)

await datatoken.approve(OCEAN, addresses.Escrow, '1000')
await Escrow.deposit(OCEAN, '100')

const funds = await Escrow.getUserFunds(await user2.getAddress(), OCEAN)
const available = BigNumber.from(funds[0])
const expectedAmount = await amountToUnits(
null,
null,
String(Number(initialDepositedEscrowAmount) + 100),
18
)
assert(available.toString() === expectedAmount)
})

it('Withdraws funds', async () => {
const availableUserFunds = await Escrow.getUserFunds(await user2.getAddress(), OCEAN)
const availableUserFundsAmount = await unitsToAmount(
null,
null,
availableUserFunds[0].toString(),
18
)

const tx = await Escrow.withdraw([OCEAN], ['50'])

assert(tx, 'failed to withdraw half of available tokens')
const funds = await Escrow.getUserFunds(await user2.getAddress(), OCEAN)
const available = BigNumber.from(funds[0])
const expectedAmount = await amountToUnits(
null,
null,
String(Number(availableUserFundsAmount) - 50),
18
)
assert(available.toString() === expectedAmount)
})

it('Authorize user1', async () => {
const tx = await Escrow.authorize(OCEAN, await user1.getAddress(), '20', '100', '3')
assert(tx, 'failed to authorize user1')
const auths = await Escrow.getAuthorizations(
OCEAN,
await user2.getAddress(),
await user1.getAddress()
)
assert(auths[0][0] === (await user1.getAddress()), 'payee address not present')
})
})
Loading