Skip to content
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

Add the ability to register a point provider #35

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions packages/relay/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ relay:
testMode: ${RELAY_TEST_MODE}
bridgeActiveStatus: true
allowedShopIdPrefix: "0x0001"
initialBalanceOfProvider: 50000

contracts:
sideChain:
Expand Down
1 change: 1 addition & 0 deletions packages/relay/config/config_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ relay:
testMode: ${RELAY_TEST_MODE}
bridgeActiveStatus: true
allowedShopIdPrefix: "0x0001"
initialBalanceOfProvider: 50000

contracts:
sideChain:
Expand Down
6 changes: 6 additions & 0 deletions packages/relay/src/common/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export class RelayConfig implements IRelayConfig {
public testMode: boolean;
public bridgeActiveStatus: boolean;
public allowedShopIdPrefix: string;
public initialBalanceOfProvider: number;

constructor() {
const defaults = RelayConfig.defaultValue();
Expand All @@ -228,6 +229,7 @@ export class RelayConfig implements IRelayConfig {
this.testMode = defaults.testMode;
this.bridgeActiveStatus = defaults.bridgeActiveStatus;
this.allowedShopIdPrefix = defaults.allowedShopIdPrefix;
this.initialBalanceOfProvider = defaults.initialBalanceOfProvider;
}

public static defaultValue(): IRelayConfig {
Expand All @@ -251,6 +253,7 @@ export class RelayConfig implements IRelayConfig {
testMode: false,
bridgeActiveStatus: true,
allowedShopIdPrefix: "0x0001",
initialBalanceOfProvider: 50000,
};
}

Expand All @@ -269,6 +272,8 @@ export class RelayConfig implements IRelayConfig {
if (config.bridgeActiveStatus !== undefined)
this.bridgeActiveStatus = config.bridgeActiveStatus.toString().toLowerCase() === "true";
if (config.allowedShopIdPrefix !== undefined) this.allowedShopIdPrefix = config.allowedShopIdPrefix;
if (config.initialBalanceOfProvider !== undefined)
this.initialBalanceOfProvider = config.initialBalanceOfProvider;
}
}

Expand Down Expand Up @@ -493,6 +498,7 @@ export interface IRelayConfig {
testMode: boolean;
bridgeActiveStatus: boolean;
allowedShopIdPrefix: string;
initialBalanceOfProvider: number;
}

export interface IContractsConfig {
Expand Down
50 changes: 50 additions & 0 deletions packages/relay/src/routers/ProviderRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ export class ProviderRouter {
}

public registerRoutes() {
this.app.post(
"/v1/provider/register",
[
body("provider").exists().trim().isEthereumAddress(),
body("signature")
.exists()
.trim()
.matches(/^(0x)[0-9a-f]{130}$/i),
],
this.provider_register.bind(this)
);

this.app.get(
"/v1/provider/balance/:provider",
[param("provider").exists().trim().isEthereumAddress()],
Expand Down Expand Up @@ -148,6 +160,44 @@ export class ProviderRouter {
);
}

private async provider_register(req: express.Request, res: express.Response) {
logger.http(`POST /v1/provider/register ${req.ip}:${JSON.stringify(req.body)}`);

const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(200).json(ResponseMessage.getErrorMessage("2001", { validation: errors.array() }));
}

const signerItem = await this.getRelaySigner(this.contractManager.sideChainProvider);
try {
const provider: string = String(req.body.provider).trim();
const signature: string = String(req.body.signature).trim();

const nonce = await this.contractManager.sideLedgerContract.nonceOf(provider);
const message = ContractUtils.getRegisterProviderMessage(provider, nonce, this.contractManager.sideChainId);
if (!ContractUtils.verifyMessage(provider, message, signature))
return res.status(200).json(ResponseMessage.getErrorMessage("1501"));

const balance = await this.contractManager.sideLedgerContract.tokenBalanceOf(provider);
const minimum = BOACoin.make(this.config.relay.initialBalanceOfProvider).value;
if (balance.lt(minimum)) {
return res.status(200).json(ResponseMessage.getErrorMessage("1511"));
}

await this.storage.postNewProvider(provider);

this.metrics.add("success", 1);
return res.status(200).json(this.makeResponseData(0, { provider }));
} catch (error: any) {
const msg = ResponseMessage.getEVMErrorMessage(error);
logger.error(`POST /v1/provider/register : ${msg.error.message}`);
this.metrics.add("failure", 1);
return res.status(200).json(this.makeResponseData(msg.code, undefined, msg.error));
} finally {
this.releaseRelaySigner(signerItem);
}
}

private async provider_balance(req: express.Request, res: express.Response) {
logger.http(`GET /v1/provider/balance/:provider ${req.ip}:${JSON.stringify(req.params)}`);

Expand Down
15 changes: 15 additions & 0 deletions packages/relay/src/storage/RelayStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -980,4 +980,19 @@ export class RelayStorage extends Storage {
});
}
/// endregion

public postNewProvider(provider: string): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
this.queryForMapper("register_provider", "postProvider", {
provider,
})
.then(() => {
return resolve();
})
.catch((reason) => {
if (reason instanceof Error) return reject(reason);
return reject(new Error(reason));
});
});
}
}
30 changes: 30 additions & 0 deletions packages/relay/src/storage/mapper/register_provider.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="register_provider">

<insert id="postProvider">
INSERT INTO register_provider
(
"provider" ,
"timestamp"
)
VALUES
(
#{provider} ,
now()
)
ON CONFLICT ("sequence")
DO UPDATE
SET
"provider" = EXCLUDED."provider",
"timestamp" = EXCLUDED."timestamp";
</insert>

<select id="read">
SELECT * FROM register_provider;
</select>

<select id="remove">
DELETE FROM register_provider WHERE sequence = ${sequence};
</select>
</mapper>
16 changes: 16 additions & 0 deletions packages/relay/src/storage/mapper/table.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,28 @@

</sql>

<sql id="register_provider">
CREATE TABLE IF NOT EXISTS register_provider
(
"sequence" BIGINT generated always as identity,
"provider" VARCHAR(42) NOT NULL,
"timestamp" TIMESTAMP,
PRIMARY KEY ("sequence")
);
CREATE SEQUENCE IF NOT EXISTS register_provider_sequence_seq;
CREATE INDEX IF NOT EXISTS register_provider_provider_index
on register_provider (provider);

</sql>

<select id="create_table">
<include refid="payments"/>
<include refid="tasks"/>
<include refid="mobiles"/>
<include refid="purchase"/>
<include refid="delegators"/>
<include refid="temporary_accounts"/>
<include refid="register_provider"/>
</select>

<select id="drop_table">
Expand All @@ -129,6 +144,7 @@
DROP TABLE purchases;
DROP TABLE delegators;
DROP TABLE temporary_accounts;
DROP TABLE register_provider;
</select>

</mapper>
5 changes: 5 additions & 0 deletions packages/relay/src/utils/ContractUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,11 @@ export class ContractUtils {
return arrayify(keccak256(encodedResult));
}

public static getRegisterProviderMessage(provider: string, nonce: BigNumberish, chainId: BigNumberish): Uint8Array {
const encodedResult = defaultAbiCoder.encode(["address", "uint256", "uint256"], [provider, chainId, nonce]);
return arrayify(keccak256(encodedResult));
}

public static async signMessage(signer: Signer, message: Uint8Array): Promise<string> {
return signer.signMessage(message);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/relay/src/utils/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ export class ResponseMessage {
["2003", "The payment ID is not exist"],
["2004", "Temporary address that does not exist"],
["2005", "Mobile notification not allowed"],
["2006", "Can not found delegator"],
["2006", "Can not find delegator"],
["2007", "The phone number format is invalid."],
["2008", "Mobile information not found."],
["2020", "The status code for this payment cannot be approved"],
["2022", "The status code for this payment cannot be cancel"],
["2022", "The status code for this payment cannot be cancelled"],
["2024", "The status code for this payment cannot process closing"],
["2025", "This payment has already been approved"],
["2026", "This payment has already been closed"],
Expand Down
Loading