|
| 1 | +import { |
| 2 | + Erc20CreateParams, |
| 3 | + NftFactory, |
| 4 | + NftCreateData, |
| 5 | + sleep, |
| 6 | + FreCreationParams, |
| 7 | + ZERO_ADDRESS, |
| 8 | + FixedRateExchange, |
| 9 | + Datatoken, |
| 10 | + ProviderFees, |
| 11 | + signHash |
| 12 | +} from '@oceanprotocol/lib' |
| 13 | +import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' |
| 14 | +import { assert } from 'chai' |
| 15 | +import Web3 from 'web3' |
| 16 | +import { homedir } from 'os' |
| 17 | +import fs from 'fs' |
| 18 | +import { fetch } from 'cross-fetch' |
| 19 | +import { AbiItem } from 'web3-utils/types' |
| 20 | + |
| 21 | +const sleepMs = 1700 |
| 22 | + |
| 23 | +const data = JSON.parse( |
| 24 | + fs.readFileSync( |
| 25 | + process.env.ADDRESS_FILE || |
| 26 | + `${homedir}/.ocean/ocean-contracts/artifacts/address.json`, |
| 27 | + 'utf8' |
| 28 | + ) |
| 29 | +) |
| 30 | +async function userQuery(user: string) { |
| 31 | + const query = { |
| 32 | + query: `query { |
| 33 | + user(id:"${user}"){ |
| 34 | + id |
| 35 | + tokenBalancesOwned {id} |
| 36 | + orders {id} |
| 37 | + freSwaps {id} |
| 38 | + totalOrders |
| 39 | + totalSales |
| 40 | + __typename |
| 41 | + }}` |
| 42 | + } |
| 43 | + const response = await fetch( |
| 44 | + 'http://127.0.0.1:9000/subgraphs/name/oceanprotocol/ocean-subgraph', |
| 45 | + { |
| 46 | + method: 'POST', |
| 47 | + body: JSON.stringify(query) |
| 48 | + } |
| 49 | + ) |
| 50 | + const data = (await response.json()).data.user |
| 51 | + return data |
| 52 | +} |
| 53 | + |
| 54 | +const addresses = data.development |
| 55 | +const web3 = new Web3('http://127.0.0.1:8545') |
| 56 | + |
| 57 | +describe('User tests', async () => { |
| 58 | + const nftName = 'test-Fixed-Price-NFT' |
| 59 | + const nftSymbol = 'TST-FIXED' |
| 60 | + const tokenURI = 'https://oceanprotocol.com/nft/fixed' |
| 61 | + const cap = '10000' |
| 62 | + const feeAmount = '0.2' |
| 63 | + const price = '3' |
| 64 | + const publishMarketSwapFee = '0.003' |
| 65 | + const templateIndex = 1 |
| 66 | + const dtAmount = '10' |
| 67 | + const datatoken = new Datatoken(web3, 8996) |
| 68 | + let datatokenAddress: string |
| 69 | + let fixedRateAddress: string |
| 70 | + let baseTokenAddress: string |
| 71 | + let feeAddress: string |
| 72 | + let Factory: NftFactory |
| 73 | + let factoryAddress: string |
| 74 | + let accounts: string[] |
| 75 | + let contractDeployer: string |
| 76 | + let publisher: string |
| 77 | + let exchangeId: string |
| 78 | + let fixedRate: FixedRateExchange |
| 79 | + let user1: string |
| 80 | + let user2: string |
| 81 | + let user3: string |
| 82 | + |
| 83 | + before(async () => { |
| 84 | + factoryAddress = addresses.ERC721Factory.toLowerCase() |
| 85 | + fixedRateAddress = addresses.FixedPrice.toLowerCase() |
| 86 | + baseTokenAddress = addresses.MockDAI.toLowerCase() |
| 87 | + Factory = new NftFactory(factoryAddress, web3) |
| 88 | + accounts = await web3.eth.getAccounts() |
| 89 | + contractDeployer = accounts[0].toLowerCase() |
| 90 | + feeAddress = accounts[1].toLowerCase() |
| 91 | + // Using different accounts from other tests to ensure that all user fields start at null |
| 92 | + publisher = accounts[6].toLowerCase() |
| 93 | + user1 = accounts[7].toLowerCase() |
| 94 | + user2 = accounts[8].toLowerCase() |
| 95 | + user3 = accounts[9].toLowerCase() |
| 96 | + }) |
| 97 | + |
| 98 | + it('Deploying a Fixed Rate Exchange & Test User Fields', async () => { |
| 99 | + const nftParams: NftCreateData = { |
| 100 | + name: nftName, |
| 101 | + symbol: nftSymbol, |
| 102 | + templateIndex: 1, |
| 103 | + tokenURI, |
| 104 | + transferable: true, |
| 105 | + owner: publisher |
| 106 | + } |
| 107 | + const erc20Params: Erc20CreateParams = { |
| 108 | + templateIndex, |
| 109 | + cap, |
| 110 | + feeAmount, |
| 111 | + paymentCollector: ZERO_ADDRESS, |
| 112 | + feeToken: ZERO_ADDRESS, |
| 113 | + minter: publisher, |
| 114 | + mpFeeAddress: feeAddress |
| 115 | + } |
| 116 | + const fixedRateParams: FreCreationParams = { |
| 117 | + fixedRateAddress, |
| 118 | + baseTokenAddress, |
| 119 | + owner: publisher, |
| 120 | + marketFeeCollector: feeAddress, |
| 121 | + baseTokenDecimals: 18, |
| 122 | + datatokenDecimals: 18, |
| 123 | + fixedRate: price, |
| 124 | + marketFee: publishMarketSwapFee, |
| 125 | + allowedConsumer: ZERO_ADDRESS, |
| 126 | + withMint: false |
| 127 | + } |
| 128 | + |
| 129 | + const result = await Factory.createNftErc20WithFixedRate( |
| 130 | + publisher, |
| 131 | + nftParams, |
| 132 | + erc20Params, |
| 133 | + fixedRateParams |
| 134 | + ) |
| 135 | + datatokenAddress = result.events.TokenCreated.returnValues[0].toLowerCase() |
| 136 | + |
| 137 | + exchangeId = |
| 138 | + result.events.NewFixedRate.returnValues.exchangeId.toLowerCase() |
| 139 | + |
| 140 | + // Check User values |
| 141 | + await sleep(sleepMs) |
| 142 | + const user = await userQuery(publisher) |
| 143 | + |
| 144 | + assert(user.id === publisher, 'incorrect value for: id') |
| 145 | + assert(user.tokenBalancesOwned.length === 0, 'incorrect tokenBalancesOwned') |
| 146 | + assert(user.orders.length === 0, 'incorrect value for: orders') |
| 147 | + assert(user.freSwaps.length === 0, 'incorrect value for: freSwaps') |
| 148 | + assert(user.totalOrders === '0', 'incorrect value for: totalOrders') |
| 149 | + assert(user.totalSales === '0', 'incorrect value for: totalSales') |
| 150 | + assert(user.__typename === 'User', 'incorrect value for: __typename') |
| 151 | + }) |
| 152 | + |
| 153 | + it('User1 buys a datatoken', async () => { |
| 154 | + const datatoken = new Datatoken(web3, 8996) |
| 155 | + // Mint datatokens as initial supply is 0 |
| 156 | + await datatoken.mint(datatokenAddress, publisher, '100') |
| 157 | + await datatoken.approve( |
| 158 | + datatokenAddress, |
| 159 | + fixedRateAddress, |
| 160 | + '100', |
| 161 | + publisher |
| 162 | + ) |
| 163 | + |
| 164 | + const daiContract = new web3.eth.Contract( |
| 165 | + MockERC20.abi as AbiItem[], |
| 166 | + addresses.MockDAI |
| 167 | + ) |
| 168 | + // user1 need DAI so that they can buy the datatoken |
| 169 | + await daiContract.methods |
| 170 | + .transfer(user1, web3.utils.toWei('100')) |
| 171 | + .send({ from: contractDeployer }) |
| 172 | + await daiContract.methods |
| 173 | + .approve(fixedRateAddress, web3.utils.toWei('10000000')) |
| 174 | + .send({ from: user1 }) |
| 175 | + |
| 176 | + // user1 has no DTs before buying one |
| 177 | + let user1Balance = await datatoken.balance(datatokenAddress, user1) |
| 178 | + assert(user1Balance === '0', 'incorrect value for: user1Balance') |
| 179 | + |
| 180 | + fixedRate = new FixedRateExchange(web3, fixedRateAddress, 8996) |
| 181 | + await fixedRate.buyDT(user1, exchangeId, dtAmount, '100') |
| 182 | + await sleep(sleepMs) |
| 183 | + |
| 184 | + user1Balance = await datatoken.balance(datatokenAddress, user1) |
| 185 | + // user1 has 1 datatoken |
| 186 | + assert(user1Balance === dtAmount, 'incorrect value for: user1Balance') |
| 187 | + |
| 188 | + // Check User values |
| 189 | + const user = await userQuery(user1) |
| 190 | + |
| 191 | + assert(user.id === user1, 'incorrect value for: id') |
| 192 | + assert(user.tokenBalancesOwned.length === 0, 'incorrect tokenBalancesOwned') |
| 193 | + assert(user.orders.length === 0, 'incorrect value for: orders') |
| 194 | + assert(user.freSwaps.length === 1, 'incorrect value for: freSwaps') |
| 195 | + assert(user.totalOrders === '0', 'incorrect value for: totalOrders') |
| 196 | + assert(user.totalSales === '0', 'incorrect value for: totalSales') |
| 197 | + assert(user.__typename === 'User', 'incorrect value for: __typename') |
| 198 | + }) |
| 199 | + it('User1 sells a datatoken', async () => { |
| 200 | + const initialUser = await userQuery(user1) |
| 201 | + await datatoken.approve(datatokenAddress, fixedRateAddress, dtAmount, user1) |
| 202 | + const tx = (await fixedRate.sellDT(user1, exchangeId, '10', '9')).events |
| 203 | + ?.Swapped |
| 204 | + |
| 205 | + assert(tx != null) |
| 206 | + const user = await userQuery(user1) |
| 207 | + |
| 208 | + assert(user.id === user1, 'incorrect value for: id') |
| 209 | + assert(user.tokenBalancesOwned.length === 0, 'incorrect tokenBalancesOwned') |
| 210 | + assert(user.orders.length === 0, 'incorrect value for: orders') |
| 211 | + assert( |
| 212 | + user.freSwaps.length === initialUser.freSwaps.length, |
| 213 | + 'incorrect value for: freSwaps' |
| 214 | + ) |
| 215 | + assert(user.totalOrders === '0', 'incorrect value for: totalOrders') |
| 216 | + assert(user.totalSales === '0', 'incorrect value for: totalSales') |
| 217 | + assert(user.__typename === 'User', 'incorrect value for: __typename') |
| 218 | + }) |
| 219 | + |
| 220 | + it('Check user fields after publishing & ordering a datatoken', async () => { |
| 221 | + // Start with publishing a new datatoken |
| 222 | + const nftParams: NftCreateData = { |
| 223 | + name: 'newNFT', |
| 224 | + symbol: 'newTST', |
| 225 | + templateIndex, |
| 226 | + tokenURI: '', |
| 227 | + transferable: true, |
| 228 | + owner: publisher |
| 229 | + } |
| 230 | + const erc20Params: Erc20CreateParams = { |
| 231 | + templateIndex, |
| 232 | + cap: '100000', |
| 233 | + feeAmount: '0', |
| 234 | + paymentCollector: ZERO_ADDRESS, |
| 235 | + feeToken: ZERO_ADDRESS, |
| 236 | + minter: publisher, |
| 237 | + mpFeeAddress: feeAddress |
| 238 | + } |
| 239 | + const result = await Factory.createNftWithErc20( |
| 240 | + publisher, |
| 241 | + nftParams, |
| 242 | + erc20Params |
| 243 | + ) |
| 244 | + const newDtAddress = result.events.TokenCreated.returnValues[0] |
| 245 | + |
| 246 | + const datatoken = new Datatoken(web3, 8996) |
| 247 | + await datatoken.mint(newDtAddress, publisher, '100', user3) |
| 248 | + const user1balance = await datatoken.balance(newDtAddress, user3) |
| 249 | + assert(Number(user1balance) === 100, 'Invalid user1 balance') |
| 250 | + |
| 251 | + const providerData = JSON.stringify({ timeout: 0 }) |
| 252 | + const providerFeeToken = ZERO_ADDRESS |
| 253 | + const providerFeeAmount = '10000' |
| 254 | + const providerValidUntil = '0' |
| 255 | + const message = web3.utils.soliditySha3( |
| 256 | + { t: 'bytes', v: web3.utils.toHex(web3.utils.asciiToHex(providerData)) }, |
| 257 | + { t: 'address', v: feeAddress }, |
| 258 | + { t: 'address', v: providerFeeToken }, |
| 259 | + { t: 'uint256', v: providerFeeAmount }, |
| 260 | + { t: 'uint256', v: providerValidUntil } |
| 261 | + ) |
| 262 | + assert(message, 'Invalid message') |
| 263 | + const { v, r, s } = await signHash(web3, message, feeAddress) |
| 264 | + const setProviderFee: ProviderFees = { |
| 265 | + providerFeeAddress: feeAddress, |
| 266 | + providerFeeToken, |
| 267 | + providerFeeAmount, |
| 268 | + v, |
| 269 | + r, |
| 270 | + s, |
| 271 | + providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)), |
| 272 | + validUntil: providerValidUntil |
| 273 | + } |
| 274 | + assert(setProviderFee, 'Invalid setProviderFee') |
| 275 | + const orderTx = await datatoken.startOrder( |
| 276 | + newDtAddress, |
| 277 | + user3, |
| 278 | + user2, |
| 279 | + 1, |
| 280 | + setProviderFee |
| 281 | + ) |
| 282 | + assert(orderTx.events.OrderStarted, 'Invalid orderTx') |
| 283 | + |
| 284 | + await sleep(2000) |
| 285 | + |
| 286 | + const user = await userQuery(user3) |
| 287 | + |
| 288 | + assert(user.id === user3, 'incorrect value for: id') |
| 289 | + assert(user.tokenBalancesOwned.length === 0, 'incorrect tokenBalancesOwned') |
| 290 | + assert(user.orders.length === 1, 'incorrect value for: orders') |
| 291 | + assert(user.freSwaps.length === 0, 'incorrect value for: freSwaps') |
| 292 | + assert(user.totalOrders === '1', 'incorrect value for: totalOrders') |
| 293 | + assert(user.totalSales === '0', 'incorrect value for: totalSales') |
| 294 | + assert(user.__typename === 'User', 'incorrect value for: __typename') |
| 295 | + }) |
| 296 | +}) |
0 commit comments