From 122332428f5aec4123f9f1ea01200977927ec8f5 Mon Sep 17 00:00:00 2001 From: Michael Kim Date: Tue, 24 Oct 2023 12:22:18 +0900 Subject: [PATCH] Change the ability to change the type of loyalty --- packages/contracts-lib/package.json | 2 +- packages/contracts/contracts/Ledger.sol | 49 +++--- .../deploy/bosagora_devnet/06_ledger.ts | 9 +- packages/contracts/package.json | 2 +- packages/contracts/src/utils/ContractUtils.ts | 11 +- packages/contracts/test/03-Ledger.test.ts | 27 ++-- packages/faker/package.json | 2 +- packages/relay/package.json | 2 +- packages/relay/src/routers/DefaultRouter.ts | 22 ++- packages/relay/src/utils/ContractUtils.ts | 20 +-- packages/relay/test/Endpoints.test.ts | 62 ++++--- packages/subgraph/generated/Ledger/Ledger.ts | 152 +++++++++--------- packages/subgraph/generated/schema.ts | 61 +++++-- .../manifest/subgraph.placeholder.yaml | 6 +- packages/subgraph/schema.graphql | 9 +- packages/subgraph/src/ledger.ts | 58 ++++++- 16 files changed, 280 insertions(+), 214 deletions(-) diff --git a/packages/contracts-lib/package.json b/packages/contracts-lib/package.json index 6a2f4493..a328c117 100644 --- a/packages/contracts-lib/package.json +++ b/packages/contracts-lib/package.json @@ -1,6 +1,6 @@ { "name": "dms-osx-lib", - "version": "1.1.6", + "version": "1.1.7", "description": "", "main": "dist/bundle-cjs.js", "module": "dist/bundle-esm.js", diff --git a/packages/contracts/contracts/Ledger.sol b/packages/contracts/contracts/Ledger.sol index 598dcaad..b4fbc13c 100644 --- a/packages/contracts/contracts/Ledger.sol +++ b/packages/contracts/contracts/Ledger.sol @@ -155,8 +155,8 @@ contract Ledger { event Deposited(address account, uint256 depositedToken, uint256 depositedValue, uint256 balanceToken); /// @notice 토큰을 인출했을 때 발생하는 이벤트 event Withdrawn(address account, uint256 withdrawnToken, uint256 withdrawnValue, uint256 balanceToken); - /// @notice 구매 후 적립되는 포인트의 종류 (0: 포인트, 1: 토큰) - event ChangedLoyaltyType(address account, LoyaltyType loyaltyType); + /// @notice 구매 후 적립되는 로열티를 토큰으로 변경했을 때 발생하는 이벤트 + event ChangedToLoyaltyToken(address account, uint256 amountToken, uint256 amountPoint, uint256 balanceToken); /// @notice 생성자 /// @param _foundationAccount 재단의 계정 @@ -593,33 +593,42 @@ contract Ledger { return loyaltyTypes[_account]; } - /// @notice 사용자가 적립할 포인트의 종류를 리턴한다 - /// @param _type 0: 포인트, 1: 토큰 + /// @notice 사용자가 적립할 로열티를 토큰으로 변경한다. /// @param _account 지갑주소 /// @param _signature 서명 /// @dev 중계서버를 통해서 호출됩니다. - function setLoyaltyType(LoyaltyType _type, address _account, bytes calldata _signature) public { - bytes32 dataHash = keccak256(abi.encode(_type, _account, nonce[_account])); + function changeToLoyaltyToken(address _account, bytes calldata _signature) public { + bytes32 dataHash = keccak256(abi.encode(_account, nonce[_account])); require(ECDSA.recover(ECDSA.toEthSignedMessageHash(dataHash), _signature) == _account, "Invalid signature"); - _setLoyaltyType(_type, _account); + _changeToLoyaltyToken(_account); } /// @notice 사용자가 적립할 포인트의 종류를 리턴한다 - /// @param _type 0: 포인트, 1: 토큰 /// @dev 사용자에 의해 직접 호출됩니다. - function setLoyaltyTypeDirect(LoyaltyType _type) public { - _setLoyaltyType(_type, msg.sender); - } - - function _setLoyaltyType(LoyaltyType _type, address _account) internal { - require(LoyaltyType.POINT <= _type && _type <= LoyaltyType.TOKEN, "Invalid value"); - - loyaltyTypes[_account] = _type; - - nonce[_account]++; - - emit ChangedLoyaltyType(_account, _type); + function changeToLoyaltyTokenDirect() public { + _changeToLoyaltyToken(msg.sender); + } + + function _changeToLoyaltyToken(address _account) internal { + if (loyaltyTypes[_account] != LoyaltyType.TOKEN) { + loyaltyTypes[_account] = LoyaltyType.TOKEN; + uint256 amountPoint; + uint256 amountToken; + if (pointBalances[_account] > 0) { + amountPoint = pointBalances[_account]; + amountToken = convertPointToToken(amountPoint); + require(tokenBalances[foundationAccount] >= amountToken, "Insufficient foundation balance"); + tokenBalances[_account] += amountToken; + tokenBalances[foundationAccount] -= amountToken; + pointBalances[_account] = 0; + } else { + amountPoint = 0; + amountToken = 0; + } + nonce[_account]++; + emit ChangedToLoyaltyToken(_account, amountToken, amountPoint, tokenBalances[_account]); + } } /// @notice 포인트와 토큰의 사용수수료률을 설정합니다. 5%를 초과한 값은 설정할 수 없습니다. diff --git a/packages/contracts/deploy/bosagora_devnet/06_ledger.ts b/packages/contracts/deploy/bosagora_devnet/06_ledger.ts index 68076c2a..85b72ab4 100644 --- a/packages/contracts/deploy/bosagora_devnet/06_ledger.ts +++ b/packages/contracts/deploy/bosagora_devnet/06_ledger.ts @@ -131,17 +131,16 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { await tx9.wait(); if (user.loyaltyType === 1) { - const loyaltyType = 1; const nonce = await ledgerContract.nonceOf(user.address); - const signature = ContractUtils.signLoyaltyType(signer, loyaltyType, nonce); - const tx10 = await ledgerContract.connect(signer).setLoyaltyType(loyaltyType, user.address, signature); + const signature = ContractUtils.signLoyaltyType(signer, nonce); + const tx10 = await ledgerContract.connect(signer).changeToLoyaltyToken(user.address, signature); console.log(`Deposit user's amount (tx: ${tx10.hash})...`); await tx10.wait(); if ((await ledgerContract.connect(signer).loyaltyTypeOf(user.address)) === 1) { - console.log(`Success setLoyaltyType...`); + console.log(`Success changeToLoyaltyToken...`); } else { - console.error(`Fail setLoyaltyType...`); + console.error(`Fail changeToLoyaltyToken...`); } } } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 9281c99d..76e05158 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "dms-osx-artifacts", - "version": "1.1.6", + "version": "1.1.7", "description": "Smart contracts that decentralized point systems", "files": [ "**/*.sol" diff --git a/packages/contracts/src/utils/ContractUtils.ts b/packages/contracts/src/utils/ContractUtils.ts index 2f750376..708092cd 100644 --- a/packages/contracts/src/utils/ContractUtils.ts +++ b/packages/contracts/src/utils/ContractUtils.ts @@ -140,16 +140,13 @@ export class ContractUtils { return signer.signMessage(message); } - public static getLoyaltyTypeMessage(type: BigNumberish, address: string, nonce: BigNumberish): Uint8Array { - const encodedResult = hre.ethers.utils.defaultAbiCoder.encode( - ["uint256", "address", "uint256"], - [type, address, nonce] - ); + public static getLoyaltyTypeMessage(address: string, nonce: BigNumberish): Uint8Array { + const encodedResult = hre.ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [address, nonce]); return arrayify(hre.ethers.utils.keccak256(encodedResult)); } - public static async signLoyaltyType(signer: Signer, type: BigNumberish, nonce: BigNumberish): Promise { - const message = ContractUtils.getLoyaltyTypeMessage(type, await signer.getAddress(), nonce); + public static async signLoyaltyType(signer: Signer, nonce: BigNumberish): Promise { + const message = ContractUtils.getLoyaltyTypeMessage(await signer.getAddress(), nonce); return signer.signMessage(message); } diff --git a/packages/contracts/test/03-Ledger.test.ts b/packages/contracts/test/03-Ledger.test.ts index f504e54a..7f0c1236 100644 --- a/packages/contracts/test/03-Ledger.test.ts +++ b/packages/contracts/test/03-Ledger.test.ts @@ -654,16 +654,13 @@ describe("Test for Ledger", () => { it("Change point type (user: 3, point type : 0)", async () => { const userIndex = 3; - const loyaltyType = 1; - const nonce = await ledgerContract.nonceOf(userWallets[userIndex].address); - const signature = ContractUtils.signLoyaltyType(userWallets[userIndex], loyaltyType, nonce); await expect( ledgerContract .connect(userWallets[userIndex].connect(hre.waffle.provider)) - .setLoyaltyTypeDirect(loyaltyType) + .changeToLoyaltyTokenDirect() ) - .to.emit(ledgerContract, "ChangedLoyaltyType") - .withNamedArgs({ account: userWallets[userIndex].address, loyaltyType }); + .to.emit(ledgerContract, "ChangedToLoyaltyToken") + .withNamedArgs({ account: userWallets[userIndex].address }); }); it("Save Purchase Data - phone and address are registered (user: 3, point type : 1)", async () => { @@ -800,14 +797,13 @@ describe("Test for Ledger", () => { it("Change point type (user: 1)", async () => { const userIndex = 1; - const loyaltyType = 1; const nonce = await ledgerContract.nonceOf(userWallets[userIndex].address); - const signature = ContractUtils.signLoyaltyType(userWallets[userIndex], loyaltyType, nonce); + const signature = ContractUtils.signLoyaltyType(userWallets[userIndex], nonce); await expect( - ledgerContract.connect(relay).setLoyaltyType(loyaltyType, userWallets[userIndex].address, signature) + ledgerContract.connect(relay).changeToLoyaltyToken(userWallets[userIndex].address, signature) ) - .to.emit(ledgerContract, "ChangedLoyaltyType") - .withNamedArgs({ account: userWallets[userIndex].address, loyaltyType }); + .to.emit(ledgerContract, "ChangedToLoyaltyToken") + .withNamedArgs({ account: userWallets[userIndex].address }); }); it("Save Purchase Data - (user: 1, point type : 1)", async () => { @@ -1037,16 +1033,13 @@ describe("Test for Ledger", () => { it("Change point type (user: 4, point type : 0)", async () => { const userIndex = 4; - const loyaltyType = 1; - const nonce = await ledgerContract.nonceOf(userWallets[userIndex].address); - const signature = ContractUtils.signLoyaltyType(userWallets[userIndex], loyaltyType, nonce); await expect( ledgerContract .connect(userWallets[userIndex].connect(hre.waffle.provider)) - .setLoyaltyTypeDirect(loyaltyType) + .changeToLoyaltyTokenDirect() ) - .to.emit(ledgerContract, "ChangedLoyaltyType") - .withNamedArgs({ account: userWallets[userIndex].address, loyaltyType }); + .to.emit(ledgerContract, "ChangedToLoyaltyToken") + .withNamedArgs({ account: userWallets[userIndex].address }); }); it("Save Purchase Data - phone and address are registered (user: 4, point type : 1)", async () => { diff --git a/packages/faker/package.json b/packages/faker/package.json index 30d66a81..3f087f7a 100644 --- a/packages/faker/package.json +++ b/packages/faker/package.json @@ -47,7 +47,7 @@ "assert": "^2.0.0", "axios": "^0.26.0", "chai": "^4.3.7", - "dms-osx-artifacts": "^1.1.6", + "dms-osx-artifacts": "^1.1.7", "dotenv": "^10.0.0", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.0", diff --git a/packages/relay/package.json b/packages/relay/package.json index 45e3f52e..e2997e41 100644 --- a/packages/relay/package.json +++ b/packages/relay/package.json @@ -58,7 +58,7 @@ "chai": "^4.3.7", "chai-http": "^4.3.7", "cors": "^2.8.5", - "dms-osx-artifacts": "^1.1.6", + "dms-osx-artifacts": "^1.1.7", "dotenv": "^10.0.0", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.0", diff --git a/packages/relay/src/routers/DefaultRouter.ts b/packages/relay/src/routers/DefaultRouter.ts index a90e0e40..29f40009 100644 --- a/packages/relay/src/routers/DefaultRouter.ts +++ b/packages/relay/src/routers/DefaultRouter.ts @@ -1,4 +1,4 @@ -import { Ledger, ShopCollection, PhoneLinkCollection, Token } from "../../typechain-types"; +import { Ledger, PhoneLinkCollection, ShopCollection, Token } from "../../typechain-types"; import { Config } from "../common/Config"; import { logger } from "../common/Logger"; import { GasPriceManager } from "../contract/GasPriceManager"; @@ -230,15 +230,14 @@ export class DefaultRouter { // 포인트의 종류를 선택하는 기능 this.app.post( - "/changeLoyaltyType", + "/changeToLoyaltyToken", [ - body("type").exists().isIn(["0", "1"]), body("account").exists().isEthereumAddress(), body("signature") .exists() .matches(/^(0x)[0-9a-f]{130}$/i), ], - this.changeLoyaltyType.bind(this) + this.changeToLoyaltyToken.bind(this) ); // 사용가능한 포인트로 전환 @@ -451,11 +450,11 @@ export class DefaultRouter { /** * 포인트의 종류를 선택한다. - * POST /changeLoyaltyType + * POST /changeToLoyaltyToken * @private */ - private async changeLoyaltyType(req: express.Request, res: express.Response) { - logger.http(`POST /changeLoyaltyType`); + private async changeToLoyaltyToken(req: express.Request, res: express.Response) { + logger.http(`POST /changeToLoyaltyToken`); const errors = validationResult(req); if (!errors.isEmpty()) { @@ -469,13 +468,12 @@ export class DefaultRouter { const signerItem = await this.getRelaySigner(); try { - const type: number = Number(req.body.type); const account: string = String(req.body.account); // 구매자의 주소 const signature: string = String(req.body.signature); // 서명 // 서명검증 const userNonce = await (await this.getLedgerContract()).nonceOf(account); - if (!ContractUtils.verifyLoyaltyType(type, account, userNonce, signature)) + if (!ContractUtils.verifyLoyaltyType(account, userNonce, signature)) return res.status(200).json( this.makeResponseData(500, undefined, { message: "Signature is not valid.", @@ -484,14 +482,14 @@ export class DefaultRouter { const tx = await (await this.getLedgerContract()) .connect(signerItem.signer) - .setLoyaltyType(type, account, signature); + .changeToLoyaltyToken(account, signature); - logger.http(`TxHash(changeLoyaltyType): `, tx.hash); + logger.http(`TxHash(changeToLoyaltyToken): `, tx.hash); return res.status(200).json(this.makeResponseData(200, { txHash: tx.hash })); } catch (error: any) { let message = ContractUtils.cacheEVMError(error as any); if (message === "") message = "Failed change point type"; - logger.error(`POST /changeLoyaltyType :`, message); + logger.error(`POST /changeToLoyaltyToken :`, message); return res.status(200).json( this.makeResponseData(500, undefined, { message, diff --git a/packages/relay/src/utils/ContractUtils.ts b/packages/relay/src/utils/ContractUtils.ts index 0ad7816d..66e8a261 100644 --- a/packages/relay/src/utils/ContractUtils.ts +++ b/packages/relay/src/utils/ContractUtils.ts @@ -162,26 +162,18 @@ export class ContractUtils { return res.toLowerCase() === account.toLowerCase(); } - public static getLoyaltyTypeMessage(type: BigNumberish, account: string, nonce: BigNumberish): Uint8Array { - const encodedResult = hre.ethers.utils.defaultAbiCoder.encode( - ["uint256", "address", "uint256"], - [type, account, nonce] - ); + public static getLoyaltyTypeMessage(account: string, nonce: BigNumberish): Uint8Array { + const encodedResult = hre.ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [account, nonce]); return arrayify(hre.ethers.utils.keccak256(encodedResult)); } - public static async signLoyaltyType(signer: Signer, type: BigNumberish, nonce: BigNumberish): Promise { - const message = ContractUtils.getLoyaltyTypeMessage(type, await signer.getAddress(), nonce); + public static async signLoyaltyType(signer: Signer, nonce: BigNumberish): Promise { + const message = ContractUtils.getLoyaltyTypeMessage(await signer.getAddress(), nonce); return signer.signMessage(message); } - public static verifyLoyaltyType( - type: BigNumberish, - account: string, - nonce: BigNumberish, - signature: string - ): boolean { - const message = ContractUtils.getLoyaltyTypeMessage(type, account, nonce); + public static verifyLoyaltyType(account: string, nonce: BigNumberish, signature: string): boolean { + const message = ContractUtils.getLoyaltyTypeMessage(account, nonce); let res: string; try { res = ethers.utils.verifyMessage(message, signature); diff --git a/packages/relay/test/Endpoints.test.ts b/packages/relay/test/Endpoints.test.ts index 9376736f..e599b8d2 100644 --- a/packages/relay/test/Endpoints.test.ts +++ b/packages/relay/test/Endpoints.test.ts @@ -403,38 +403,6 @@ describe("Test of Server", function () { }); }); - context("Change loyalty type", () => { - it("Check loyalty type - before", async () => { - const userIndex = 0; - const loyaltyType = await ledgerContract.loyaltyTypeOf(users[userIndex].address); - expect(loyaltyType).to.equal(0); - }); - - it("Send loyalty type", async () => { - const loyaltyType = 1; - const userIndex = 0; - const nonce = await ledgerContract.nonceOf(users[userIndex].address); - const signature = await ContractUtils.signLoyaltyType(users[userIndex], loyaltyType, nonce); - const uri = URI(serverURL).directory("changeLoyaltyType"); - const url = uri.toString(); - const response = await client.post(url, { - type: loyaltyType, - account: users[userIndex].address, - signature, - }); - - expect(response.data.code).to.equal(200); - expect(response.data.data).to.not.equal(undefined); - expect(response.data.data.txHash).to.match(/^0x[A-Fa-f0-9]{64}$/i); - }); - - it("Check point type - after", async () => { - const userIndex = 0; - const loyaltyType = await ledgerContract.loyaltyTypeOf(users[userIndex].address); - expect(loyaltyType).to.equal(1); - }); - }); - context("payPoint & payToken", () => { const purchase: IPurchaseData = { purchaseId: "P000001", @@ -619,6 +587,36 @@ describe("Test of Server", function () { assert.ok(response.data.data.txHash !== undefined); }); }); + + context("Change loyalty type", () => { + it("Check loyalty type - before", async () => { + const userIndex = 0; + const loyaltyType = await ledgerContract.loyaltyTypeOf(users[userIndex].address); + expect(loyaltyType).to.equal(0); + }); + + it("Send loyalty type", async () => { + const userIndex = 0; + const nonce = await ledgerContract.nonceOf(users[userIndex].address); + const signature = await ContractUtils.signLoyaltyType(users[userIndex], nonce); + const uri = URI(serverURL).directory("changeToLoyaltyToken"); + const url = uri.toString(); + const response = await client.post(url, { + account: users[userIndex].address, + signature, + }); + + expect(response.data.code).to.equal(200); + expect(response.data.data).to.not.equal(undefined); + expect(response.data.data.txHash).to.match(/^0x[A-Fa-f0-9]{64}$/i); + }); + + it("Check point type - after", async () => { + const userIndex = 0; + const loyaltyType = await ledgerContract.loyaltyTypeOf(users[userIndex].address); + expect(loyaltyType).to.equal(1); + }); + }); }); context("Test token & point relay endpoints - using phone", () => { diff --git a/packages/subgraph/generated/Ledger/Ledger.ts b/packages/subgraph/generated/Ledger/Ledger.ts index cb3828fb..59c09935 100644 --- a/packages/subgraph/generated/Ledger/Ledger.ts +++ b/packages/subgraph/generated/Ledger/Ledger.ts @@ -10,16 +10,16 @@ import { BigInt } from "@graphprotocol/graph-ts"; -export class ChangedLoyaltyType extends ethereum.Event { - get params(): ChangedLoyaltyType__Params { - return new ChangedLoyaltyType__Params(this); +export class ChangedToLoyaltyToken extends ethereum.Event { + get params(): ChangedToLoyaltyToken__Params { + return new ChangedToLoyaltyToken__Params(this); } } -export class ChangedLoyaltyType__Params { - _event: ChangedLoyaltyType; +export class ChangedToLoyaltyToken__Params { + _event: ChangedToLoyaltyToken; - constructor(event: ChangedLoyaltyType) { + constructor(event: ChangedToLoyaltyToken) { this._event = event; } @@ -27,8 +27,16 @@ export class ChangedLoyaltyType__Params { return this._event.parameters[0].value.toAddress(); } - get loyaltyType(): i32 { - return this._event.parameters[1].value.toI32(); + get amountToken(): BigInt { + return this._event.parameters[1].value.toBigInt(); + } + + get amountPoint(): BigInt { + return this._event.parameters[2].value.toBigInt(); + } + + get balanceToken(): BigInt { + return this._event.parameters[3].value.toBigInt(); } } @@ -1001,6 +1009,66 @@ export class _payTokenCall_dataStruct extends ethereum.Tuple { } } +export class ChangeToLoyaltyTokenCall extends ethereum.Call { + get inputs(): ChangeToLoyaltyTokenCall__Inputs { + return new ChangeToLoyaltyTokenCall__Inputs(this); + } + + get outputs(): ChangeToLoyaltyTokenCall__Outputs { + return new ChangeToLoyaltyTokenCall__Outputs(this); + } +} + +export class ChangeToLoyaltyTokenCall__Inputs { + _call: ChangeToLoyaltyTokenCall; + + constructor(call: ChangeToLoyaltyTokenCall) { + this._call = call; + } + + get _account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get _signature(): Bytes { + return this._call.inputValues[1].value.toBytes(); + } +} + +export class ChangeToLoyaltyTokenCall__Outputs { + _call: ChangeToLoyaltyTokenCall; + + constructor(call: ChangeToLoyaltyTokenCall) { + this._call = call; + } +} + +export class ChangeToLoyaltyTokenDirectCall extends ethereum.Call { + get inputs(): ChangeToLoyaltyTokenDirectCall__Inputs { + return new ChangeToLoyaltyTokenDirectCall__Inputs(this); + } + + get outputs(): ChangeToLoyaltyTokenDirectCall__Outputs { + return new ChangeToLoyaltyTokenDirectCall__Outputs(this); + } +} + +export class ChangeToLoyaltyTokenDirectCall__Inputs { + _call: ChangeToLoyaltyTokenDirectCall; + + constructor(call: ChangeToLoyaltyTokenDirectCall) { + this._call = call; + } +} + +export class ChangeToLoyaltyTokenDirectCall__Outputs { + _call: ChangeToLoyaltyTokenDirectCall; + + constructor(call: ChangeToLoyaltyTokenDirectCall) { + this._call = call; + } +} + export class ChangeToPayablePointCall extends ethereum.Call { get inputs(): ChangeToPayablePointCall__Inputs { return new ChangeToPayablePointCall__Inputs(this); @@ -1411,74 +1479,6 @@ export class SetFeeCall__Outputs { } } -export class SetLoyaltyTypeCall extends ethereum.Call { - get inputs(): SetLoyaltyTypeCall__Inputs { - return new SetLoyaltyTypeCall__Inputs(this); - } - - get outputs(): SetLoyaltyTypeCall__Outputs { - return new SetLoyaltyTypeCall__Outputs(this); - } -} - -export class SetLoyaltyTypeCall__Inputs { - _call: SetLoyaltyTypeCall; - - constructor(call: SetLoyaltyTypeCall) { - this._call = call; - } - - get _type(): i32 { - return this._call.inputValues[0].value.toI32(); - } - - get _account(): Address { - return this._call.inputValues[1].value.toAddress(); - } - - get _signature(): Bytes { - return this._call.inputValues[2].value.toBytes(); - } -} - -export class SetLoyaltyTypeCall__Outputs { - _call: SetLoyaltyTypeCall; - - constructor(call: SetLoyaltyTypeCall) { - this._call = call; - } -} - -export class SetLoyaltyTypeDirectCall extends ethereum.Call { - get inputs(): SetLoyaltyTypeDirectCall__Inputs { - return new SetLoyaltyTypeDirectCall__Inputs(this); - } - - get outputs(): SetLoyaltyTypeDirectCall__Outputs { - return new SetLoyaltyTypeDirectCall__Outputs(this); - } -} - -export class SetLoyaltyTypeDirectCall__Inputs { - _call: SetLoyaltyTypeDirectCall; - - constructor(call: SetLoyaltyTypeDirectCall) { - this._call = call; - } - - get _type(): i32 { - return this._call.inputValues[0].value.toI32(); - } -} - -export class SetLoyaltyTypeDirectCall__Outputs { - _call: SetLoyaltyTypeDirectCall; - - constructor(call: SetLoyaltyTypeDirectCall) { - this._call = call; - } -} - export class WithdrawCall extends ethereum.Call { get inputs(): WithdrawCall__Inputs { return new WithdrawCall__Inputs(this); diff --git a/packages/subgraph/generated/schema.ts b/packages/subgraph/generated/schema.ts index 65c382b8..7713887c 100644 --- a/packages/subgraph/generated/schema.ts +++ b/packages/subgraph/generated/schema.ts @@ -11,7 +11,7 @@ import { BigDecimal } from "@graphprotocol/graph-ts"; -export class ChangedLoyaltyType extends Entity { +export class ChangedToLoyaltyToken extends Entity { constructor(id: Bytes) { super(); this.set("id", Value.fromBytes(id)); @@ -19,25 +19,28 @@ export class ChangedLoyaltyType extends Entity { save(): void { let id = this.get("id"); - assert(id != null, "Cannot save ChangedLoyaltyType entity without an ID"); + assert( + id != null, + "Cannot save ChangedToLoyaltyToken entity without an ID" + ); if (id) { assert( id.kind == ValueKind.BYTES, - `Entities of type ChangedLoyaltyType must have an ID of type Bytes but the id '${id.displayData()}' is of type ${id.displayKind()}` + `Entities of type ChangedToLoyaltyToken must have an ID of type Bytes but the id '${id.displayData()}' is of type ${id.displayKind()}` ); - store.set("ChangedLoyaltyType", id.toBytes().toHexString(), this); + store.set("ChangedToLoyaltyToken", id.toBytes().toHexString(), this); } } - static loadInBlock(id: Bytes): ChangedLoyaltyType | null { - return changetype( - store.get_in_block("ChangedLoyaltyType", id.toHexString()) + static loadInBlock(id: Bytes): ChangedToLoyaltyToken | null { + return changetype( + store.get_in_block("ChangedToLoyaltyToken", id.toHexString()) ); } - static load(id: Bytes): ChangedLoyaltyType | null { - return changetype( - store.get("ChangedLoyaltyType", id.toHexString()) + static load(id: Bytes): ChangedToLoyaltyToken | null { + return changetype( + store.get("ChangedToLoyaltyToken", id.toHexString()) ); } @@ -67,17 +70,43 @@ export class ChangedLoyaltyType extends Entity { this.set("account", Value.fromBytes(value)); } - get loyaltyType(): i32 { - let value = this.get("loyaltyType"); + get amountToken(): BigInt { + let value = this.get("amountToken"); if (!value || value.kind == ValueKind.NULL) { - return 0; + throw new Error("Cannot return null for a required field."); } else { - return value.toI32(); + return value.toBigInt(); } } - set loyaltyType(value: i32) { - this.set("loyaltyType", Value.fromI32(value)); + set amountToken(value: BigInt) { + this.set("amountToken", Value.fromBigInt(value)); + } + + get amountPoint(): BigInt { + let value = this.get("amountPoint"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set amountPoint(value: BigInt) { + this.set("amountPoint", Value.fromBigInt(value)); + } + + get balanceToken(): BigInt { + let value = this.get("balanceToken"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set balanceToken(value: BigInt) { + this.set("balanceToken", Value.fromBigInt(value)); } get blockNumber(): BigInt { diff --git a/packages/subgraph/manifest/subgraph.placeholder.yaml b/packages/subgraph/manifest/subgraph.placeholder.yaml index 2d620b07..67270541 100644 --- a/packages/subgraph/manifest/subgraph.placeholder.yaml +++ b/packages/subgraph/manifest/subgraph.placeholder.yaml @@ -16,7 +16,7 @@ dataSources: apiVersion: 0.0.7 language: wasm/assemblyscript entities: - - ChangedLoyaltyType + - ChangedToLoyaltyToken - ChangedToPayablePoint - Deposited - PaidPoint @@ -31,8 +31,8 @@ dataSources: - name: Ledger file: $DMS_OSX_MODULE/artifacts/contracts/Ledger.sol/Ledger.json eventHandlers: - - event: ChangedLoyaltyType(address,uint8) - handler: handleChangedLoyaltyType + - event: ChangedToLoyaltyToken(address,uint256,uint256,uint256) + handler: handleChangedToLoyaltyToken - event: ChangedToPayablePoint(bytes32,address,uint256,uint256,uint256) handler: handleChangedToPayablePoint - event: Deposited(address,uint256,uint256,uint256) diff --git a/packages/subgraph/schema.graphql b/packages/subgraph/schema.graphql index 33b234d6..70cd9cfa 100644 --- a/packages/subgraph/schema.graphql +++ b/packages/subgraph/schema.graphql @@ -1,7 +1,9 @@ -type ChangedLoyaltyType @entity(immutable: true) { +type ChangedToLoyaltyToken @entity(immutable: true) { id: Bytes! account: Bytes! # address - loyaltyType: Int! # uint8 + amountToken: BigInt! # uint256 + amountPoint: BigInt! # uint256 + balanceToken: BigInt! # uint256 blockNumber: BigInt! blockTimestamp: BigInt! transactionHash: Bytes! @@ -145,7 +147,8 @@ enum UserAction { PaidToken, DepositedToken, WithdrawnToken, - SettlementToken + SettlementToken, + ChangedToToken } enum AssetFlow { diff --git a/packages/subgraph/src/ledger.ts b/packages/subgraph/src/ledger.ts index eb73608c..28830960 100644 --- a/packages/subgraph/src/ledger.ts +++ b/packages/subgraph/src/ledger.ts @@ -1,5 +1,5 @@ import { - ChangedLoyaltyType as ChangedLoyaltyTypeEvent, + ChangedToLoyaltyToken as ChangedToLoyaltyTokenEvent, ChangedToPayablePoint as ChangedToPayablePointEvent, Deposited as DepositedEvent, PaidPoint as PaidPointEvent, @@ -12,7 +12,7 @@ import { Withdrawn as WithdrawnEvent, } from "../generated/Ledger/Ledger"; import { - ChangedLoyaltyType, + ChangedToLoyaltyToken, ChangedToPayablePoint, Deposited, PaidPoint, @@ -30,16 +30,20 @@ import { import { BigInt, Bytes } from "@graphprotocol/graph-ts"; import { AmountUnit, NullAccount, NullBytes32 } from "./utils"; -export function handleChangedLoyaltyType(event: ChangedLoyaltyTypeEvent): void { - let entity = new ChangedLoyaltyType(event.transaction.hash.concatI32(event.logIndex.toI32())); +export function handleChangedToLoyaltyToken(event: ChangedToLoyaltyTokenEvent): void { + let entity = new ChangedToLoyaltyToken(event.transaction.hash.concatI32(event.logIndex.toI32())); entity.account = event.params.account; - entity.loyaltyType = event.params.loyaltyType; + entity.amountToken = event.params.amountToken.div(AmountUnit); + entity.amountPoint = event.params.amountPoint.div(AmountUnit); + entity.balanceToken = event.params.balanceToken.div(AmountUnit); entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); + + handleChangedToLoyaltyTokenForHistory(event); } export function handleChangedToPayablePoint(event: ChangedToPayablePointEvent): void { @@ -513,3 +517,47 @@ export function handlePaidPointForHistory(event: PaidPointEvent): void { entity.transactionHash = event.transaction.hash; entity.save(); } + +export function handleChangedToLoyaltyTokenForHistory(event: ChangedToLoyaltyTokenEvent): void { + let balanceEntity = handleChangedBalancePoint( + event.params.account, + BigInt.fromI32(0), + event.block.number, + event.block.timestamp, + event.transaction.hash + ); + + let entity = new UserTradeHistory(event.transaction.hash.concatI32(event.logIndex.toI32())); + entity.account = event.params.account; + entity.action = "ChangedToToken"; + entity.assetFlow = "Use"; + entity.amountPoint = event.params.amountPoint.div(AmountUnit); + entity.amountToken = BigInt.fromI32(0); + entity.value = event.params.amountPoint.div(AmountUnit); + entity.balancePoint = BigInt.fromI32(0); + entity.balanceToken = balanceEntity.token; + entity.purchaseId = ""; + entity.shopId = NullBytes32; + + entity.blockNumber = event.block.number; + entity.blockTimestamp = event.block.timestamp; + entity.transactionHash = event.transaction.hash; + entity.save(); + + entity = new UserTradeHistory(event.transaction.hash.concatI32(event.logIndex.toI32())); + entity.account = event.params.account; + entity.action = "ChangedToToken"; + entity.assetFlow = "Save"; + entity.amountPoint = BigInt.fromI32(0); + entity.amountToken = event.params.amountToken.div(AmountUnit); + entity.value = event.params.amountPoint.div(AmountUnit); + entity.balancePoint = BigInt.fromI32(0); + entity.balanceToken = event.params.balanceToken.div(AmountUnit); + entity.purchaseId = ""; + entity.shopId = NullBytes32; + + entity.blockNumber = event.block.number; + entity.blockTimestamp = event.block.timestamp; + entity.transactionHash = event.transaction.hash; + entity.save(); +}