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

Implement API service without business logic #89

Closed
Keith-CY opened this issue Dec 28, 2022 · 45 comments
Closed

Implement API service without business logic #89

Keith-CY opened this issue Dec 28, 2022 · 45 comments
Assignees
Labels
enhancement New feature or request

Comments

@Keith-CY
Copy link
Member

Keith-CY commented Dec 28, 2022

PRD: #54

@Keith-CY Keith-CY added the enhancement New feature or request label Dec 28, 2022
@Keith-CY Keith-CY added this to the 2022/12/29 - 2023/01/05 milestone Dec 28, 2022
@PainterPuppets
Copy link
Contributor

#1 (comment)

Which directory should the api of a kuai project be placed in?

@Keith-CY
Copy link
Member Author

#1 (comment)

Which directory should the api of a kuai project be placed in?

How about creating a private demo repo and link dependencies to local kuai project

@PainterPuppets
Copy link
Contributor

#1 (comment)
Which directory should the api of a kuai project be placed in?

How about creating a private demo repo and link dependencies to local kuai project

Ok, I thought kuai project template included the api, similar to nestjs

@Keith-CY
Copy link
Member Author

#1 (comment)
Which directory should the api of a kuai project be placed in?

How about creating a private demo repo and link dependencies to local kuai project

Ok, I thought kuai project template included the api, similar to nestjs

It would be better to provide a template of API service if we could.

The template could be added in kuai and initialize a project by kuai-cli linked locally

@Keith-CY
Copy link
Member Author

Keith-CY commented Dec 29, 2022

#1 (comment)
Which directory should the api of a kuai project be placed in?

How about creating a private demo repo and link dependencies to local kuai project

Ok, I thought kuai project template included the api, similar to nestjs

Would you add a backend template or create a new project from scratch temporarily? If one of them will be done by you, I will finish the UI part.
Or you can take over the UI part and I'm going to work on the server part

@PainterPuppets
Copy link
Contributor

Would you add a backend template or create a new project from scratch temporarily? If one of them will be done by you, I will finish the UI part. Or you can take over the UI part and I'm going to work on the server part

Ok, I'm adding the api part to the initial project template. I can follow the documentation to mock api input and output first, and then integrate the specific logic after the store part is done.

And other qustion, mvp project files should be placed where, a new repository?

@Keith-CY
Copy link
Member Author

Would you add a backend template or create a new project from scratch temporarily? If one of them will be done by you, I will finish the UI part. Or you can take over the UI part and I'm going to work on the server part

Ok, I'm adding the api part to the initial project template. I can follow the documentation to mock api input and output first, and then integrate the specific logic after the store part is done.

And other qustion, mvp project files should be placed where, a new repository?

Opening a private repo in https://github.com/Magickbase/ is fine

@Keith-CY
Copy link
Member Author

How is it going

@PainterPuppets
Copy link
Contributor

PainterPuppets commented Jan 11, 2023

The current api server side code is here: https://github.com/Magickbase/kuai-mvp-server
run this projecy need link the local kuai package, the operating steps are written in readme.md

need review this peoject structure, if not problem , this structure will integrate to kuai init as project template

@PainterPuppets
Copy link
Contributor

create a pull request: https://github.com/Magickbase/kuai-mvp-server/pull/1

@Keith-CY Keith-CY removed this from the 2022/12/29 - 2023/01/05 milestone Jan 18, 2023
@Keith-CY
Copy link
Member Author

https://github.com/Magickbase/kuai-mvp-server/pull/1 has been approved by 2 reviewers and was merged into the main branch. Please add it in kuai as the backend template.

@PainterPuppets
Copy link
Contributor

Will be pull request later

@Keith-CY
Copy link
Member Author

After the template is ready in kuai, please add a directory named samples, and use the cli to create an mvp-dapp project in the directory, just as nest.js dis https://github.com/nestjs/nest/tree/master/sample @PainterPuppets

Once the mvp-dapp skeleton is ready, we should start the actual coding. I'd like to divide the job into 3 tasks from the perspective of MVC

  1. View:
    1. when claim, set, clear APIs are called, inputs and outputs will be returned from storage model, and should be transformed into a raw transaction to the front-end
    2. when read, load APIs are called, structured data should be returned to the front-end
  2. Controller: define the interface of APIs and parse arguments. The second function has been implemented by @kuai/io, so only function one should be considered. Mainly about the identity of requests cuz business logic is simple.
  3. Model: the storage model. The MVP dapp simply covers the preset methods, so only the schema should be implemented additionally.

Would you pick one up from tasks? @PainterPuppets @Daryl-L @yanguoyu

The tasks not picked will be arranged later(about 18:30 this day).

@PainterPuppets
Copy link
Contributor

I will be doing the controller part, which is more related to kuai/io.

@Daryl-L
Copy link
Contributor

Daryl-L commented Jan 29, 2023

After the template is ready in kuai, please add a directory named samples, and use the cli to create an mvp-dapp project in the directory, just as nest.js dis https://github.com/nestjs/nest/tree/master/sample @PainterPuppets

Once the mvp-dapp skeleton is ready, we should start the actual coding. I'd like to divide the job into 3 tasks from the perspective of MVC

  1. View:

    1. when claim, set, clear APIs are called, inputs and outputs will be returned from storage model, and should be transformed into a raw transaction to the front-end
    2. when read, load APIs are called, structured data should be returned to the front-end
  2. Controller: define the interface of APIs and parse arguments. The second function has been implemented by @kuai/io, so only function one should be considered. Mainly about the identity of requests cuz business logic is simple.

  3. Model: the storage model. The MVP dapp simply covers the preset methods, so only the schema should be implemented additionally.

Would you pick one up from tasks? @PainterPuppets @Daryl-L @yanguoyu

The tasks not picked will be arranged later(about 18:30 this day).

I think the View partial is front end in this project according to this demo, right?

@Keith-CY
Copy link
Member Author

After the template is ready in kuai, please add a directory named samples, and use the cli to create an mvp-dapp project in the directory, just as nest.js dis nestjs/nest@master/sample @PainterPuppets
Once the mvp-dapp skeleton is ready, we should start the actual coding. I'd like to divide the job into 3 tasks from the perspective of MVC

  1. View:

    1. when claim, set, clear APIs are called, inputs and outputs will be returned from storage model, and should be transformed into a raw transaction to the front-end
    2. when read, load APIs are called, structured data should be returned to the front-end
  2. Controller: define the interface of APIs and parse arguments. The second function has been implemented by @kuai/io, so only function one should be considered. Mainly about the identity of requests cuz business logic is simple.

  3. Model: the storage model. The MVP dapp simply covers the preset methods, so only the schema should be implemented additionally.

Would you pick one up from tasks? @PainterPuppets @Daryl-L @yanguoyu
The tasks not picked will be arranged later(about 18:30 this day).

I think the View partial is front end in this project according to this demo, right?

It could be done in either backend or front-end.

The main work of View is to transform inputs and outputs into a transaction to sign.

If inputs and outputs are returned from API, front-end should construct the transaction and request a signature via metamask, then the View is in UI.

If inputs and outputs are returned from model but are constructed into a transaction just before responding to the front-end, then the View is in backend.

Either is fine.

@yanguoyu
Copy link
Contributor

I think there is only Model left for me. I will do it.

@Daryl-L
Copy link
Contributor

Daryl-L commented Jan 29, 2023

I'm going to finish View part.

@Keith-CY
Copy link
Member Author

Will be pull request later

How is it going?

@Keith-CY
Copy link
Member Author

Will be pull request later

How is it going?

PR: #121

@Keith-CY
Copy link
Member Author

Keith-CY commented Jan 31, 2023

After the template is ready in kuai, please add a directory named samples, and use the cli to create an mvp-dapp project in the directory, just as nest.js dis nestjs/nest@master/sample @PainterPuppets

Once the mvp-dapp skeleton is ready, we should start the actual coding. I'd like to divide the job into 3 tasks from the perspective of MVC

  1. View:

    1. when claim, set, clear APIs are called, inputs and outputs will be returned from storage model, and should be transformed into a raw transaction to the front-end
    2. when read, load APIs are called, structured data should be returned to the front-end
  2. Controller: define the interface of APIs and parse arguments. The second function has been implemented by @kuai/io, so only function one should be considered. Mainly about the identity of requests cuz business logic is simple.

  3. Model: the storage model. The MVP dapp simply covers the preset methods, so only the schema should be implemented additionally.

Would you pick one up from tasks? @PainterPuppets @Daryl-L @yanguoyu

The tasks not picked will be arranged later(about 18:30 this day).

Please create a project named mvp-dapp in kuai/samples, then we can start the coding of MVP @PainterPuppets

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 1, 2023

Model, View, and Controller will be ready for code review by 02-03

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 3, 2023

Model, View, and Controller will be ready for code review by 02-03

Any problem with proposing PRs for review today?

@Daryl-L
Copy link
Contributor

Daryl-L commented Feb 3, 2023

pr for resource binding to initiate Store while registered #125

@Daryl-L
Copy link
Contributor

Daryl-L commented Feb 3, 2023

Model, View, and Controller will be ready for code review by 02-03

Any problem with proposing PRs for review today?

The PR for View will be proposed as soon as possible rest of today. And I think the bootstrap is more complex than expected after finishing the ResourceBinding, so I think maybe it is necessary for me to participate in.

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 4, 2023

Model definition. #126

@Daryl-L
Copy link
Contributor

Daryl-L commented Feb 4, 2023

View #127

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 6, 2023

View: #127
Controller: #124
Model: #126
have been merged, the backend service could be launched now

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

Some logic may have to be complemented in app.controller.ts, all routes are expected to parse params/body, and redirect them to model which returns inputs/outputs or structured data, then respond them via view. If the response is a structured data, UI will render them directly, if the response is a transaction constructed by view, UI will request a signature from metamask

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

Some logic may have to be complemented in app.controller.ts, all routes are expected to parse params/body, and redirect them to model which returns inputs/outputs or structured data, then respond them via view. If the response is a structured data, UI will render them directly, if the response is a transaction constructed by view, UI will request a signature from metamask

@PainterPuppets

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

We may need 2 models for the controller

The one that has been added(https://github.com/ckb-js/kuai/blob/develop/packages/samples/mvp-dapp/src/record/record.model.ts) works with a claimed store, it can be set, get and load, but cannot be initialized by the claim method

So another model is required to transform a group of omnilock cells into a store cell(named record in this case).

The possible workflow would be as follows:

  1. user => claim 610 CKB => model_a gathers 10 * 61 CKB and turns them into 1 * 610 CKB with a specific pattern for record model, say, data starts with mvp_dapp`
  2. user => load store => record model syncs the 610 CKB cell by the pattern set by model_a and returns the empty data structure parsed from the 610 CKB
  3. user => set store => record model syncs the 610 CKB and adopts modification on it, returns inputs/outputs, in this case, 610 CKB/610 CKB

Correct me if it doesn't work or is unnecessary @yanguoyu

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 7, 2023

We may need 2 models for the controller

The one that has been added(https://github.com/ckb-js/kuai/blob/develop/packages/samples/mvp-dapp/src/record/record.model.ts) works with a claimed store, it can be set, get and load, but cannot be initialized by the claim method

So another model is required to transform a group of omnilock cells into a store cell(named record in this case).

The possible workflow would be as follows:

  1. user => claim 610 CKB => model_a gathers 10 * 61 CKB and turns them into 1 * 610 CKB with a specific pattern for record model, say, data starts with mvp_dapp`
  2. user => load store => record model syncs the 610 CKB cell by the pattern set by model_a and returns the empty data structure parsed from the 610 CKB
  3. user => set store => record model syncs the 610 CKB and adopts modification on it, returns inputs/outputs, in this case, 610 CKB/610 CKB

Correct me if it doesn't work or is unnecessary @yanguoyu

I thought ActorBase is enough, it only needs to gather spec256 cells, and there are no data needed to serialize or deserialize.

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

We may need 2 models for the controller The one that has been added(develop/packages/samples/mvp-dapp/src/record/record.model.ts) works with a claimed store, it can be set, get and load, but cannot be initialized by the claim method So another model is required to transform a group of omnilock cells into a store cell(named record in this case). The possible workflow would be as follows: 1. user => claim 610 CKB => model_a gathers 10 * 61 CKB and turns them into 1 * 610 CKB with a specific pattern for record model, say, data starts with mvp_dapp2. user => load store =>record modelsyncs the 610 CKB cell by the pattern set bymodel_aand returns the emptydata structureparsed from the 610 CKB 3. user => set store =>record modelsyncs the 610 CKB and adopts modification on it, returnsinputs/outputs, in this case, 610 CKB/610 CKB` Correct me if it doesn't work or is unnecessary @yanguoyu

I thought ActorBase is enough, it only needs to gather spec256 cells, and there are no data needed to serialize or deserialize.

secp256k1 doesn't work with metamask, so omnilock will be used, but it's not the point. My point is how can the record model construct a cell to store data without a claim action. Will the cells be gathered by demand, like,

  1. user => load store => no cells
  2. user => set store => fetch a cell and update its data
  3. user => set store => update the same cell if capacity is enough, or fetch a new cell to construct a bigger cell for storage

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 7, 2023

Do you mean how to init a cell with initialization data? @Keith-CY

I think it may init like this:
Init the output cell's data by initOnChain, and then gather needs capacity cells as inputs.

const initModel = new RecordModel()
const { data } = initModel.initOnChain({
  data: {
    profile: [],
    addresses: [],
    custom: [],
    dweb: [],
  }
})
const tx = {
inputs,
outputs,
outputs_data: [data]
}

Then broadcast the tx to init a cell

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

Do you mean how to init a cell with initialization data? @Keith-CY

I think it may init like this: Init the output cell's data by initOnChain, and then gather needs capacity cells as inputs.

const initModel = new RecordModel()
const { data } = initModel.initOnChain({
  data: {
    profile: [],
    addresses: [],
    custom: [],
    dweb: [],
  }
})
const tx = {
inputs,
outputs,
outputs_data: [data]
}

Then broadcast the tx to init a cell

Get it, except one point we can talk about later. If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding.
After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding. After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

Here's my understanding(#85 (comment)), but it was not confirmed or disputed by @Daryl-L

From the code(https://github.com/ckb-js/kuai/blob/develop/packages/models/src/resource-binding/manager.ts#L20) we can see that resource-binding doesn't care about an explicit pattern, the key was roughly set type_script + lock_script.

That means, not every cell sent from resource binding manager to store will update internal state of the store, store should filter out cells those not match pattern defined in store

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding. After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

Here's my understanding(#85 (comment)), but it was not confirmed or disputed by @Daryl-L

From the code(https://github.com/ckb-js/kuai/blob/develop/packages/models/src/resource-binding/manager.ts#L20) we can see that resource-binding doesn't care about an explicit pattern, the key was roughly set type_script + lock_script.

That means, not every cell sent from resource binding manager to store will update internal state of the store, store should filter out cells those not match pattern defined in store

Do you mean I forget to filter cells in handleCall by pattern? If so, I will add it later.

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding. After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

Here's my understanding(#85 (comment)), but it was not confirmed or disputed by @Daryl-L From the code(develop/packages/models/src/resource-binding/manager.ts#L20) we can see that resource-binding doesn't care about an explicit pattern, the key was roughly set type_script + lock_script. That means, not every cell sent from resource binding manager to store will update internal state of the store, store should filter out cells those not match pattern defined in store

Do you mean I forget to filter cells in handleCall by pattern? If so, I will add it later.

It should be done in resource-binding, but could be too hurry to finish it for now, filtering in store would be simple in the MVP dapp

@Daryl-L
Copy link
Contributor

Daryl-L commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding. After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

Here's my understanding(#85 (comment)), but it was not confirmed or disputed by @Daryl-L

From the code(https://github.com/ckb-js/kuai/blob/develop/packages/models/src/resource-binding/manager.ts#L20) we can see that resource-binding doesn't care about an explicit pattern, the key was roughly set type_script + lock_script.

That means, not every cell sent from resource binding manager to store will update internal state of the store, store should filter out cells those not match pattern defined in store

So the resource binding manager should not only filter the cells by type script and lock script, but also parse the data with storage and filter the cells out by pattern, right?

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

If 2 services are running, without a pattern for record, how can the cell initialized by service A be detected by service B

The above-defined RecordModel is only used to get the outputs_data, but not a RecordModel for resource-binding, RecordModel need to define a pattern with resource-binding. After the tx is broadcast, service B will receive the tx and store it in record by resource-binding.

Here's my understanding(#85 (comment)), but it was not confirmed or disputed by @Daryl-L From the code(develop/packages/models/src/resource-binding/manager.ts#L20) we can see that resource-binding doesn't care about an explicit pattern, the key was roughly set type_script + lock_script. That means, not every cell sent from resource binding manager to store will update internal state of the store, store should filter out cells those not match pattern defined in store

So the resource binding manager should not only filter the cells by type script and lock script, but also parse the data with storage and filter the cells out by pattern, right?

We haven't discussed it much, so there's no conclusion yet.

For me, yes. Resource-binding means providing resources asked by others. Say that, module A declares that it wants A, B, C, to Z, they are all letters, then resource-binding should give letters to module A, but not characters which covers letters and digits.

However, in a meeting, we've talked about a compromise that resource-binding could provide a superset of cells to store while store filter them again to update its internal state.

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 7, 2023

This is my understanding of the MVP API process:

  1. claim
    • get init output_data
    • create output by lock
    • gather inputs
    • create tx and return
  2. read
    • register lock/type by resource-binding
    • generator/get store
    • send message to store to save data to state
    • return data by store
  3. set
    • register lock/type by resource-binding
    • generator/get store
    • send message to store to save data to state
    • send message to store to set data
    • get inputs and outputs from store
    • if capacity is not enough, gather extra inputs
    • create tx and return
  4. load: I think it seems as read when calling it without a path.
  5. clear
    • register lock/type by resource-binding
    • generator/get store
    • send message to store to save data to state
    • clear data by store
    • get inputs and outputs from store
    • create tx and return

I think there are some things we need to implement:

  1. gather extra inputs when the inputs' capacity is not enough.
  2. generator and register store, I don't know when we need to register store and what will be set as the store's path.
  3. create an instance of ChainSource to instantiate a resource-binding.
  4. gather a tx from inputs, outputs, and outputs_data

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 7, 2023

This is my understanding of the MVP API process:

  1. claim
    • get init output_data * create output by lock * gather inputs * create tx and return
  2. read
    • register lock/type by resource-binding * generator/get store * send message to store to save data to state * return data by store
  3. set
    • register lock/type by resource-binding * generator/get store * send message to store to save data to state * send message to store to set data * get inputs and outputs from store * if capacity is not enough, gather extra inputs * create tx and return
  4. load: I think it seems as read when calling it without a path.
  5. clear
    • register lock/type by resource-binding * generator/get store * send message to store to save data to state * clear data by store * get inputs and outputs from store * create tx and return

I think there are some things we need to implement:

  1. gather extra inputs when the inputs' capacity is not enough.
  2. generator and register store, I don't know when we need to register store and what will be set as the store's path.
  3. create an instance of ChainSource to instantiate a resource-binding.
  4. gather a tx from inputs, outputs, and outputs_data

The confusion may come from the timing of claim and register a store

As the PRD(#54 (comment)) said

claim(capacity): Transaction: claim a group of cells with a given capacity as the user info Store to store user info

claim(capacity) gathers cells to instantiate a store with empty data. after claim, a cell should be on the chain to hold the user's info. Then the user's info could be updated and loaded.

Besides, the capacity of a store is declared at first, so once data written to the cell is out of limit, it should be rejected.

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 8, 2023

Missing parts:

  1. Controller, assigned to @PainterPuppets :
    1. Restful request URI, as /claim/:address
    2. Parameters validation
    3. Error handling
    4. Delegate messages to model and format responses with view
  2. Model and claim method, assigned to @yanguoyu :
    1. Omnilock Model:
      1. Claim: gather cells into an integrated cell with specific capacity and predefined data prefix
      2. Instantiate omnilock model and register it in the resource binding
    2. Record Model:
      1. Update: receive message of set and return inputs/outputs
  3. Resource-binding, assigned @Daryl-L :
    1. Chain source instance
      1. get cells to initiate states of stores
      2. get blocks to update states of stores

@yanguoyu
Copy link
Contributor

yanguoyu commented Feb 9, 2023

Model and claim method #137

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

No branches or pull requests

4 participants