mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
Merge pull request #34 from oceanprotocol/feature/search
added searchAssets
This commit is contained in:
commit
966bb01e5c
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@oceanprotocol/squid",
|
"name": "@oceanprotocol/squid",
|
||||||
"version": "0.1.0-beta.16",
|
"version": "0.1.0-beta.17",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@oceanprotocol/squid",
|
"name": "@oceanprotocol/squid",
|
||||||
"version": "0.1.0-beta.16",
|
"version": "0.1.0-beta.17",
|
||||||
"description": "JavaScript client library for Ocean Protocol",
|
"description": "JavaScript client library for Ocean Protocol",
|
||||||
"main": "dist/squid.js",
|
"main": "dist/squid.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -2,11 +2,11 @@ import Config from "./models/Config"
|
|||||||
|
|
||||||
export default class ConfigProvider {
|
export default class ConfigProvider {
|
||||||
|
|
||||||
public static getConfig() {
|
public static getConfig(): Config {
|
||||||
return ConfigProvider.config
|
return ConfigProvider.config
|
||||||
}
|
}
|
||||||
|
|
||||||
public static configure(config: Config) {
|
public static setConfig(config: Config) {
|
||||||
|
|
||||||
ConfigProvider.config = config
|
ConfigProvider.config = config
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
import fetch from "node-fetch"
|
import Config from "../models/Config"
|
||||||
import Logger from "../utils/Logger"
|
import Logger from "../utils/Logger"
|
||||||
|
import AquariusConnectorProvider from "./AquariusConnectorProvider"
|
||||||
|
|
||||||
export default class Aquarius {
|
export default class Aquarius {
|
||||||
public static async getAccessUrl(accessToken: any, payload: any): Promise<string> {
|
|
||||||
|
|
||||||
const accessUrl = await fetch(`${accessToken.service_endpoint}/${accessToken.resource_id}`, {
|
private url: string
|
||||||
method: "POST",
|
|
||||||
body: payload,
|
constructor(config: Config) {
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json",
|
this.url = config.aquariusUri
|
||||||
},
|
}
|
||||||
})
|
|
||||||
|
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
|
||||||
|
|
||||||
|
const accessUrl = await AquariusConnectorProvider.getConnector().post(
|
||||||
|
`${accessToken.service_endpoint}/${accessToken.resource_id}`,
|
||||||
|
payload)
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
return response.text()
|
return response.text()
|
||||||
@ -27,4 +32,40 @@ export default class Aquarius {
|
|||||||
|
|
||||||
return accessUrl
|
return accessUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async queryMetadata(query): Promise<any[]> {
|
||||||
|
|
||||||
|
const result = await AquariusConnectorProvider.getConnector().post(
|
||||||
|
this.url + "/api/v1/aquarius/assets/ddo/query",
|
||||||
|
JSON.stringify(query))
|
||||||
|
.then((response: any) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
Logger.log("Failed: ", response.status, response.statusText)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
Logger.error("Error fetching querying metadata: ", error)
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public async queryMetadataByText(query): Promise<any[]> {
|
||||||
|
|
||||||
|
const result = await AquariusConnectorProvider.getConnector().get(
|
||||||
|
this.url + "/api/v1/aquarius/assets/ddo/query",
|
||||||
|
JSON.stringify(query))
|
||||||
|
.then((response: any) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
Logger.log("Failed: ", response.status, response.statusText)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
Logger.error("Error fetching querying metadata: ", error)
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
29
src/aquarius/AquariusConnector.ts
Normal file
29
src/aquarius/AquariusConnector.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import fetch from "node-fetch"
|
||||||
|
import { URL } from "url"
|
||||||
|
|
||||||
|
export default class AquariusConnector {
|
||||||
|
|
||||||
|
public post(url, payload) {
|
||||||
|
return fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
body: payload,
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(url, payload) {
|
||||||
|
const fullUrl = new URL(url)
|
||||||
|
for (const key of Object.keys(payload)) {
|
||||||
|
fullUrl.searchParams.append(key, payload[key])
|
||||||
|
}
|
||||||
|
return fetch(fullUrl, {
|
||||||
|
method: "GET",
|
||||||
|
body: null,
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
23
src/aquarius/AquariusConnectorProvider.ts
Normal file
23
src/aquarius/AquariusConnectorProvider.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import Logger from "../utils/Logger"
|
||||||
|
import AquariusConnector from "./AquariusConnector"
|
||||||
|
|
||||||
|
export default class AquariusConnectorProvider {
|
||||||
|
|
||||||
|
public static setConnector(connector: AquariusConnector) {
|
||||||
|
|
||||||
|
Logger.log("setting", typeof connector.constructor.name)
|
||||||
|
|
||||||
|
AquariusConnectorProvider.connector = connector
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getConnector() {
|
||||||
|
|
||||||
|
if (!AquariusConnectorProvider.connector) {
|
||||||
|
AquariusConnectorProvider.connector = new AquariusConnector()
|
||||||
|
}
|
||||||
|
Logger.log("getting", typeof AquariusConnectorProvider.connector.constructor.name)
|
||||||
|
return AquariusConnectorProvider.connector
|
||||||
|
}
|
||||||
|
|
||||||
|
private static connector: AquariusConnector = null
|
||||||
|
}
|
@ -1,14 +1,20 @@
|
|||||||
|
import ConfigProvider from "../ConfigProvider"
|
||||||
|
import Aquarius from "./Aquarius"
|
||||||
|
|
||||||
export default class AquariusProvider {
|
export default class AquariusProvider {
|
||||||
|
|
||||||
public static setAquarius(aquarius) {
|
public static setAquarius(aquarius: Aquarius) {
|
||||||
|
|
||||||
AquariusProvider.aquarius = aquarius
|
AquariusProvider.aquarius = aquarius
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getAquarius() {
|
public static getAquarius() {
|
||||||
|
|
||||||
|
if (!AquariusProvider.aquarius) {
|
||||||
|
AquariusProvider.aquarius = new Aquarius(ConfigProvider.getConfig())
|
||||||
|
}
|
||||||
return AquariusProvider.aquarius
|
return AquariusProvider.aquarius
|
||||||
}
|
}
|
||||||
|
|
||||||
private static aquarius
|
private static aquarius: Aquarius = null
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export default class Config {
|
export default class Config {
|
||||||
public providerUri: string
|
public aquariusUri: string
|
||||||
public nodeUri: string
|
public nodeUri: string
|
||||||
public web3Provider: any
|
public web3Provider: any
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import Aquarius from "../aquarius/Aquarius"
|
|
||||||
import AquariusProvider from "../aquarius/AquariusProvider"
|
import AquariusProvider from "../aquarius/AquariusProvider"
|
||||||
import ConfigProvider from "../ConfigProvider"
|
import ConfigProvider from "../ConfigProvider"
|
||||||
import Keeper from "../keeper/Keeper"
|
import Keeper from "../keeper/Keeper"
|
||||||
@ -13,8 +12,7 @@ export default class Ocean {
|
|||||||
public static async getInstance(config) {
|
public static async getInstance(config) {
|
||||||
|
|
||||||
if (!Ocean.instance) {
|
if (!Ocean.instance) {
|
||||||
ConfigProvider.configure(config)
|
ConfigProvider.setConfig(config)
|
||||||
AquariusProvider.setAquarius(Aquarius)
|
|
||||||
Ocean.instance = new Ocean(await Keeper.getInstance())
|
Ocean.instance = new Ocean(await Keeper.getInstance())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,4 +88,8 @@ export default class Ocean {
|
|||||||
|
|
||||||
return orders
|
return orders
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async searchAssets(query): Promise<any[]> {
|
||||||
|
return AquariusProvider.getAquarius().queryMetadata(query)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
36
test/aquarius/Aquarius.test.ts
Normal file
36
test/aquarius/Aquarius.test.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import * as assert from "assert"
|
||||||
|
import Aquarius from "../../src/aquarius/Aquarius"
|
||||||
|
import AquariusConnectorProvider from "../../src/aquarius/AquariusConnectorProvider"
|
||||||
|
import config from "../config"
|
||||||
|
import AquariusConnectorMock from "../mocks/AquariusConnector.mock"
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
AquariusConnectorProvider.setConnector(new AquariusConnectorMock())
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Aquarius", () => {
|
||||||
|
|
||||||
|
describe("#queryMetadata()", () => {
|
||||||
|
|
||||||
|
it("should query metadata", async () => {
|
||||||
|
|
||||||
|
const aquarius: Aquarius = new Aquarius(config)
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
offset: 100,
|
||||||
|
page: 0,
|
||||||
|
query: {
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
text: "Office",
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: any[] = await aquarius.queryMetadata(query)
|
||||||
|
assert(result)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
@ -1,5 +1,7 @@
|
|||||||
import Config from "../src/models/Config"
|
import Config from "../src/models/Config"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
aquariusUri: "http://localhost:5000",
|
||||||
nodeUri: "http://localhost:8545",
|
nodeUri: "http://localhost:8545",
|
||||||
|
web3Provider: null,
|
||||||
} as Config
|
} as Config
|
||||||
|
@ -5,13 +5,13 @@ import ContractBaseMock from "../mocks/ContractBase.Mock"
|
|||||||
|
|
||||||
const wrappedContract = new ContractBaseMock("OceanToken")
|
const wrappedContract = new ContractBaseMock("OceanToken")
|
||||||
|
|
||||||
before(async () => {
|
describe("ContractWrapperBase", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
wrappedContract.initMock()
|
wrappedContract.initMock()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("ContractWrapperBase", () => {
|
|
||||||
|
|
||||||
describe("#call()", () => {
|
describe("#call()", () => {
|
||||||
|
|
||||||
|
@ -3,13 +3,13 @@ import ConfigProvider from "../../src/ConfigProvider"
|
|||||||
import ContractHandler from "../../src/keeper/ContractHandler"
|
import ContractHandler from "../../src/keeper/ContractHandler"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
ConfigProvider.configure(config)
|
|
||||||
await ContractHandler.deployContracts()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("ContractHandler", () => {
|
describe("ContractHandler", () => {
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
|
await ContractHandler.deployContracts()
|
||||||
|
})
|
||||||
|
|
||||||
describe("#get()", () => {
|
describe("#get()", () => {
|
||||||
|
|
||||||
it("should load and get OceanToken correctly", async () => {
|
it("should load and get OceanToken correctly", async () => {
|
||||||
|
@ -6,13 +6,13 @@ import config from "../config"
|
|||||||
|
|
||||||
let keeper: Keeper
|
let keeper: Keeper
|
||||||
|
|
||||||
before(async () => {
|
describe("Keeper", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
keeper = await Keeper.getInstance()
|
keeper = await Keeper.getInstance()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Keeper", () => {
|
|
||||||
|
|
||||||
describe("public interface", () => {
|
describe("public interface", () => {
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import Aquarius from "../../src/aquarius/Aquarius"
|
|||||||
|
|
||||||
export default class AquariusMock extends Aquarius {
|
export default class AquariusMock extends Aquarius {
|
||||||
|
|
||||||
public static async getAccessUrl(accessToken: any, payload: any): Promise<string> {
|
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
|
||||||
return "http://test/test"
|
return "http://test/test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
test/mocks/AquariusConnector.mock.ts
Normal file
17
test/mocks/AquariusConnector.mock.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import AquariusConnector from "../../src/aquarius/AquariusConnector"
|
||||||
|
|
||||||
|
export default class AquariusConnectorMock extends AquariusConnector {
|
||||||
|
|
||||||
|
public async post(url: string, payload: any) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: () => {
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
text: () => {
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,15 +9,15 @@ import config from "../config"
|
|||||||
let ocean: Ocean
|
let ocean: Ocean
|
||||||
let accounts: Account[]
|
let accounts: Account[]
|
||||||
|
|
||||||
before(async () => {
|
describe("Account", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
ocean = await Ocean.getInstance(config)
|
ocean = await Ocean.getInstance(config)
|
||||||
|
|
||||||
accounts = await ocean.getAccounts()
|
accounts = await ocean.getAccounts()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Account", () => {
|
|
||||||
|
|
||||||
describe("#getOceanBalance()", () => {
|
describe("#getOceanBalance()", () => {
|
||||||
|
|
||||||
|
@ -19,9 +19,11 @@ let testAsset: Asset
|
|||||||
let accounts: Account[]
|
let accounts: Account[]
|
||||||
let testPublisher: Account
|
let testPublisher: Account
|
||||||
|
|
||||||
before(async () => {
|
describe("Asset", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
AquariusProvider.setAquarius(AquariusMock)
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
|
AquariusProvider.setAquarius(new AquariusMock(config))
|
||||||
|
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
ocean = await Ocean.getInstance(config)
|
ocean = await Ocean.getInstance(config)
|
||||||
@ -30,9 +32,7 @@ before(async () => {
|
|||||||
testAsset = new Asset(testName, testDescription, testPrice, testPublisher)
|
testAsset = new Asset(testName, testDescription, testPrice, testPublisher)
|
||||||
|
|
||||||
await ocean.register(testAsset)
|
await ocean.register(testAsset)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Asset", () => {
|
|
||||||
|
|
||||||
describe("#purchase()", () => {
|
describe("#purchase()", () => {
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {assert} from "chai"
|
import {assert} from "chai"
|
||||||
|
import AquariusProvider from "../../src/aquarius/AquariusProvider"
|
||||||
import ConfigProvider from "../../src/ConfigProvider"
|
import ConfigProvider from "../../src/ConfigProvider"
|
||||||
import ContractHandler from "../../src/keeper/ContractHandler"
|
import ContractHandler from "../../src/keeper/ContractHandler"
|
||||||
import Account from "../../src/ocean/Account"
|
import Account from "../../src/ocean/Account"
|
||||||
@ -6,6 +7,7 @@ import Asset from "../../src/ocean/Asset"
|
|||||||
import Ocean from "../../src/ocean/Ocean"
|
import Ocean from "../../src/ocean/Ocean"
|
||||||
import Order from "../../src/ocean/Order"
|
import Order from "../../src/ocean/Order"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
|
import AquariusMock from "../mocks/Aquarius.mock"
|
||||||
|
|
||||||
let ocean: Ocean
|
let ocean: Ocean
|
||||||
let accounts: Account[]
|
let accounts: Account[]
|
||||||
@ -17,17 +19,18 @@ const description = "This asset is pure owange"
|
|||||||
const price = 100
|
const price = 100
|
||||||
const timeout = 100000000
|
const timeout = 100000000
|
||||||
|
|
||||||
before(async () => {
|
describe("Ocean", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
|
AquariusProvider.setAquarius(new AquariusMock(config))
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
ocean = await Ocean.getInstance(config)
|
ocean = await Ocean.getInstance(config)
|
||||||
accounts = await ocean.getAccounts()
|
accounts = await ocean.getAccounts()
|
||||||
|
|
||||||
testPublisher = accounts[0]
|
testPublisher = accounts[0]
|
||||||
testAsset = new Asset(name, description, price, testPublisher)
|
testAsset = new Asset(name, description, price, testPublisher)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Ocean", () => {
|
|
||||||
|
|
||||||
describe("#getInstance()", () => {
|
describe("#getInstance()", () => {
|
||||||
|
|
||||||
@ -84,4 +87,26 @@ describe("Ocean", () => {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("#searchAssets()", () => {
|
||||||
|
|
||||||
|
it("should search for assets", async () => {
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
offset: 100,
|
||||||
|
page: 0,
|
||||||
|
query: {
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
text: "Office",
|
||||||
|
}
|
||||||
|
|
||||||
|
const assets: any[] = await ocean.searchAssets(query)
|
||||||
|
|
||||||
|
assert(assets)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {assert} from "chai"
|
import {assert} from "chai"
|
||||||
|
import AquariusProvider from "../../src/aquarius/AquariusProvider"
|
||||||
import ConfigProvider from "../../src/ConfigProvider"
|
import ConfigProvider from "../../src/ConfigProvider"
|
||||||
import ContractHandler from "../../src/keeper/ContractHandler"
|
import ContractHandler from "../../src/keeper/ContractHandler"
|
||||||
import AccessStatus from "../../src/models/AccessStatus"
|
import AccessStatus from "../../src/models/AccessStatus"
|
||||||
@ -7,6 +8,7 @@ import Asset from "../../src/ocean/Asset"
|
|||||||
import Ocean from "../../src/ocean/Ocean"
|
import Ocean from "../../src/ocean/Ocean"
|
||||||
import Order from "../../src/ocean/Order"
|
import Order from "../../src/ocean/Order"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
|
import AquariusMock from "../mocks/Aquarius.mock"
|
||||||
|
|
||||||
const testName = "Order Test Asset"
|
const testName = "Order Test Asset"
|
||||||
const testDescription = "This asset is pure owange"
|
const testDescription = "This asset is pure owange"
|
||||||
@ -20,8 +22,11 @@ let accounts: Account[]
|
|||||||
let testPublisher: Account
|
let testPublisher: Account
|
||||||
let testConsumer: Account
|
let testConsumer: Account
|
||||||
|
|
||||||
before(async () => {
|
describe("Order", () => {
|
||||||
ConfigProvider.configure(config)
|
|
||||||
|
before(async () => {
|
||||||
|
ConfigProvider.setConfig(config)
|
||||||
|
AquariusProvider.setAquarius(new AquariusMock(config))
|
||||||
await ContractHandler.deployContracts()
|
await ContractHandler.deployContracts()
|
||||||
ocean = await Ocean.getInstance(config)
|
ocean = await Ocean.getInstance(config)
|
||||||
accounts = await ocean.getAccounts()
|
accounts = await ocean.getAccounts()
|
||||||
@ -30,9 +35,7 @@ before(async () => {
|
|||||||
// register an asset to play around with
|
// register an asset to play around with
|
||||||
testAsset = new Asset(testName, testDescription, testPrice, testPublisher)
|
testAsset = new Asset(testName, testDescription, testPrice, testPublisher)
|
||||||
await ocean.register(testAsset)
|
await ocean.register(testAsset)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Order", () => {
|
|
||||||
|
|
||||||
describe("#pay()", async () => {
|
describe("#pay()", async () => {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user