Use Case 1: Buy-Side - Investor Trading
Overview
The following is a step by step guide, that highlights the association of the key values in each of the messages that are involved in onboarding the investor, the asset, and the creation and execution of the primary sale.
This includes from the investor (buyer) perspective:
- The creation of the owner profile, which creates a FinID that is used to identify the investor (buyer in this case).
- The deposit request of funds that will be used to pay for the transaction, and routing the request to the payment organization.
- The execution against an existing primary sale intent.
- The posting of a secondary market sell intent for the asset.
- The execution of a posted secondary sell intent.
- The execution of a posted secondary buy intent.
API Integration Flow
The following table will walk you through step-by-step involved in the trading interface integration, which enables the investor to be onboarded, invest in primary sale, and participate in secondary market:
# | API Reference | Description | |||
---|---|---|---|---|---|
Onboard the Investor | |||||
1 | Create Investor Account | Registers the investor on FinP2P network. | |||
2 | Bind Investor to a Custodian | Send a request to the associated custodian to onboard the investor on the custody system, which in turn will provide the public key (finID) that is associated with the investor. | |||
3 | (Add Certificates) | [Optional] Attach certificates such as KYC and AML. For FinP2P proposed certificate specifications, please refer to FinP2P Certificates Spec reference page. | |||
4 | Attach Documentation | [Optional] Add additional documentation to provide additional information about the issuer. | |||
5 | Share Investor with Payments Service | Link the investor to the applicable payments organization responsible for handling the payments leg for the investor. Note: If the user is associated with an organization offering escrow payment services to the user in question, this step can be omitted | |||
Fund the Account | |||||
6 | Create a Deposit Instructions Request | This step creates a deposit instructions request, which will be routed to the given payment service organization. Please note based on the integration to the payment system, the response to this message could take time to process by that organization. In such case the response will not contain the instructions immediately (processed asynchronously). Otherwise, response will contain deposit instruction that could be used in the case funds wire transfer is required. | |||
7 | Process Deposit Instructions Response | OR, If the message is processed asynchronous, use the Get operation message to poll the status and content for the response to the request. | |||
Perform an Investment in a Primary Sale of a Given Asset | |||||
8 | Query Assets for Open Primary Sale Intent | Get assets that were made available with for the organization, and look for open intents to inform the investor of availability to buy distributed assets. Look for intents of type PrimarySale that have a status of Active. | |||
9 | Execute the Intent | Invest in the given open Primary Sale by executing the intent. This will create and send an execution plan to all the participants in this token issuance that is part of the primary sale. | |||
10 | Query Execution Plan for Progress | Use the GraphQL subscription to listen to the event when an execution plan based on the execution plan id received during the intent (token) execution, in order to track for the progress of the execution plan. | |||
Participate in Secondary Trading for a Given Asset - Sell the Asset | |||||
11 | Create a Selling Intent | Create a sell intent against the given asset that the investor owns, which can be executed by a buyer investor. The intent is of type "SELLINGINTENT" which will include the asset transfer and payment settlement details required to execute the intent from the seller perspective. This will include the assets being sold, and the organization and account in which you wish the sale proceeds to be routed to. | |||
12 | Subscribe to Intent Execution Event | Use GraphQL subscription to listen to the event when an execution plan is created (added), and look for the plan that is associated with the given intent Id that was assigned when the intent was created. This will indicate that intent execution was requested. Retain the execution plan Id to track it. | |||
13 | <https://finp2p-docs.ownera.io/reference/the-graphql-schema> | Use the GraphQL subscription to listen to the event when an execution plan based on the execution plan id you got from the previous step, in order to track for the progress of the execution plan. | |||
Participate in Secondary Trading for a Given Asset - Request an execution against an Intent | |||||
14 | <https://finp2p-docs.ownera.io/reference/the-graphql-schema> | Get assets that are shared with the given organization, and look for open intents to inform the investor of availability to buy assets. Look for intents of type “BuyingIntent” or “SellingIntent”. | |||
15 | <https://finp2p-docs.ownera.io/reference/the-graphql-schema> | Send an execution request against the given intent (buy or sell). If the message was handled synchronously, the response section will contain the receipt which is the proof of ownership on the token(s) received in the trade. Rejection could be due to varying reasons such as investor accreditation failure, lack of funding, timeout on the execution operation, etc. | |||
16 | Subscribe to Intent Execution Event | Use GraphQL subscription to listen to the event when an execution plan is created (added), and look for the plan that is associated with the given intent Id that was assigned when the intent was created. This will indicate that intent execution was requested. Retain the execution plan Id to track it. | |||
17 | Subscribe for receipts | Uses GraphQL call in order to receive the cryptographically signed receipt for the payment or for the token transfer. | |||
Execute a Repo/Loan Intent | |||||
18 | Create a Repo/Loan Intent | Create a Repo/Loan intent which includes the negotiated commercials to execute the repo on behalf of the borrower and lender involved in the trade. | |||
19 | Execute the Repo/Loan Intent | Execute the Repo/Loan intent which will initiate the execution plan that will wait till indicated settlement to begin to trade. | |||
Execute a Redeem Intent | |||||
20 | Execute the Redeem Intent | Execute the Repo/Loan intent which will initiate the execution plan that will wait till indicated settlement to begin to trade. | |||
Request Withdrawal of funds | |||||
21 | Request Funds Withdrawal | The user has the option to withdraw the funds that are in the given account by putting in a request for withdrawal. This request is routed to the given payment service provider to process. If the response is processed synchronously, the response section will contain the withdrawal details. | |||
22 | Poll for Response from Payment Service | If the request is processed asynchronously, use the get operations to receive the response. |
Testing Your Integration
You can test your buy-side integration by requesting from Ownera a sell-side sandbox which will provide you with a full suite of simulation for tokenization and payment processing.
Example: Investment in Primary Sale
The following is an example for the onboarding and funding of the user, and the execution of an investment in a given primary sale:
Create user profile:
Create the investor profile that is going to be trading against primary/secondary intents, which will assign a unique Resource ID for the given investor to be used when performing actions on-behalf of investor.
curl --location --request POST '<router url>/finapi/profiles/owner' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
"isCompleted": true,
"response": {
"id": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
},
"type": "profile"
}
Bind the user to the given custodian:
Send a request to the custodian to onboard the investor on the custody platform, which will return the public key that will be used to identify the investor. The process is an asynchronous process, and therefore you will need to
curl --location --request POST '<router url>/finapi/profiles/owner/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/account' \
--header 'Content-Type: application/json' \
--data-raw '{
"orgId": "custody-service"
}'
{
"cid":"e3c59abb-f296-4556-a4c6-9c0e397ad6f9",
"isCompleted":false,
"type":"addAccount"
}
Poll the request until it is completed:
Poll for the completion of the custodian investor onboarding.
curl --location --request POST '<router url>/operations/status/e3c59abb-f296-4556-a4c6-9c0e397ad6f9' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
"cid": "e3c59abb-f296-4556-a4c6-9c0e397ad6f9",
"isCompleted": true,
"response": {
"custodyOrgId": "custody-service",
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835"
},
"type": "account"
}
Attach certificates to the given user:
The attached certificate in this case is called "ownerInfo" which is used to assign a name, email, and what type the investor is.
curl --location --request POST 'http://<router url>/finapi/profiles/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/certificates' \
--header 'Content-Type: application/json' \
--data-raw '{
"type": "ownerInfo",
"issuanceDate": 1668598695,
"expirationDate": 1700134695,
"data": "{\"email\":\"[email protected]\",\"name\":\"Investor\",\"type\":\"individual\"}"
}'
{
"id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}
Additional certificate include a KYC/AML
{
"type": "KYC/AML",
"issuanceDate": 1692605934,
"expirationDate": 1700134695,
"data": "{\"name\":\"AML/KYC Compliance\",\"country\":\"usa\",\"info\":[{\"type\":\"text\",\"name\":\"Certificate ID\",\"value\":\"WFJXV5HQTO\"},{\"type\":\"text\",\"name\":\"Country\",\"value\":\"usa\"}]}"
}
{
"id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}
And Accreditation certificate
{
"type": "Accreditation",
"issuanceDate": 1692605934,
"expirationDate": 1700134695,
"data": "{\"name\":\"Certificate of Accreditation\",\"country\":\"usa\",\"info\":[{\"type\":\"text\",\"name\":\"Certificate ID\",\"value\":\"NC368IV14VR\"},{\"type\":\"text\",\"name\":\"Country\",\"value\":\"usa\"}]}"
}
{
"id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}
Upload and attached documents to certificates:
Upload a document to the given certificate, pointing to a location and name of the file to upload.
curl --location --request POST 'http://<router url>/finapi/profiles/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/certificates/ec634170-8c62-4d55-b324-0391eb30fac1' \
--form 'kya doc=@"/kyc.pdf"'
Associate the user with the given payments processing organization:
Associate (share) the user to a given organization, in this case, to the organization that is going to provide escrow/payments services for the investor.
curl --location --request POST 'http://<router url>/profiles/bank-il:101:a0f25042-c27c-4184-ae93-6488e43541a8/share' \
--header 'Content-Type: application/json' \
--data-raw '{
"organizations": [
"payment-service"
]
}'
n/a
Request deposit instructions:
Place a deposit request for funds into the given escrow account. The account is designated by the buyer fin ID and its associated escrow organization ID. The instruction below requests a USD fiat deposit in the amount of $100,000 into "payment-service" organization. The custody service supplied will be used to send a deposit signature request onbehalf of investor.
curl --location --request POST 'http://<router url>/finapi/payments/deposit' \
--header 'Content-Type: application/json' \
--data-raw '{
"profileId": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144",
"account": {
"account": {
"type": "finId",
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payment-service",
"custodian": {
"orgId": "custody-service"
}
},
"asset": {
"type": "fiat",
"code": "USD"
}
},
"amount": "1000000",
"nonce": "712a41ae225cf0b64f09c2a1ecf6b436b126276d3247da3a0000000000000000"
}'
{
"cid": "9cd41679a9cfb99e856f1351908df952cae259296a6f49660000000063aaf015",
"isCompleted": false,
"type": "deposit"
}
Get status on request:
Run a get operations to pull for the response on the deposit request.
curl --location --request GET 'http://<router url>/finapi/operations/status/9cd41679a9cfb99e856f1351908df952cae259296a6f49660000000063aaf015'
{
"isCompleted": true,
"response": {
"depositInstruction": {
"depositInstruction": {
"account": {
"account": {
"finId": "035049f22c30b46477c0991c6de41cf6428cee58bc5dcfe56513b7f16a624185b2",
"orgId": "ownera-escrow",
"type": "finId"
},
"asset": {
"code": "USD",
"type": "fiat"
}
},
"description": "Bank Adress|100 West Park Avenue|Beneficiary Name|Bank ABC, LCC|Bank Name|First International Bank|Account number|1292929292|Account type|Custodial|Routing number|10299393393|Bic Swift Code|FIRBILITXXX|Reference number|1J2JDJDJDFHJ"
},
"operationId": "690c41f1-bfb6-480f-bd92-8470b8183db6"
}
},
"type": "deposit"
}
Query for open primary sales that are open for investment:
Query for open intents that are of type "primarySale" that have status of "ACTIVE". The intent information will provide you with the details required to execute the intent. The example shows a token of type building that has 100000 tokens available for investment in valued at 2 USD each. The intent will be executed via the given payments processing organization "payments-service".
query OpenIntents {
assets {
nodes {
id
name
organizationId
issuerId
denomination {
code
}
certificates {
nodes {
data
documents {
nodes {
id
uri
}
}
}
}
intents(
filter: [{key: "type", operator: EQ, value: "primarySale"}, {key: "status", operator: EQ, value: "ACTIVE"}]
) {
nodes {
id
type
start
end
status
remainingQuantity
intent {
... on PrimarySale {
issuerId
assetTerm {
amount
asset {
... on FinP2PAsset {
resourceId
}
}
}
assetInstruction {
account {
identifier {
... on FinP2PAssetAccount {
finId
orgId
custodian {
orgId
}
}
}
}
destinationAccount {
identifier {
... on FinP2PAssetAccount {
finId
orgId
custodian {
orgId
}
}
}
}
}
settlementTerm {
unitValue
asset {
... on FiatAsset {
code
}
}
}
sellingSettlementInstruction {
accounts {
identifier {
... on Iban {
code
}
... on FinP2PAssetAccount {
finId
orgId
}
}
}
}
}
}
}
}
}
}
}
{
"data": {
"assets": {
"nodes": [
{
"id": "bank-de:102:f96240dc-8365-475b-84e2-9611bb5e5bc0",
"name": "A-9499371996",
"organizationId": "bank-de",
"issuerId": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
"denomination": {
"code": "USD"
},
"certificates": {
"nodes": [
{
"data": "{\"publicName\":\"A-9499371996\",\"officialName\":\"Asset 9499371996, Inc\",\"description\":\"Asset 9499371996 description\",\"info\":[]}",
"documents": {
"nodes": [
{
"id": "6406e901-9ddf-404e-9222-71934cb36554",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/6406e901-9ddf-404e-9222-71934cb36554"
},
{
"id": "deb86f68-dc25-4d33-bfe6-83ff817cdd5c",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/deb86f68-dc25-4d33-bfe6-83ff817cdd5c"
},
{
"id": "9c405932-e894-4661-a15b-60802d3c782d",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/9c405932-e894-4661-a15b-60802d3c782d"
}
]
}
},
{
"data": "{\"currentNAV\":{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140},\"history\":[{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140}]}",
"documents": {
"nodes": []
}
}
]
},
"intents": {
"nodes": [
{
"id": "bank-de:105:d07ab369-8bf2-4740-a055-1d11d2edfd38",
"type": "primarySale",
"start": 1716991745,
"end": 1811538000,
"status": "ACTIVE",
"remainingQuantity": "10000",
"intent": {
"issuerId": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
"assetTerm": {
"amount": "1000",
"asset": {
"resourceId": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884"
}
},
"assetInstruction": {
"account": {
"identifier": {
"finId": "0284550512e33ea4215a55f164c286fc27e0a474a9a15becbc4a63d89a885d1b1e",
"orgId": "bank-uk",
"custodian": {
"orgId": "custody-service"
}
}
},
"destinationAccount": null
},
"settlementTerm": {
"unitValue": "2",
"asset": {
"code": "USD"
}
},
"sellingSettlementInstruction": {
"accounts": [
{
"identifier": {
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payments-service"
}
}
]
}
}
}
]
}
}
]
}
}
}
Place a Primary Sale Execution Request:
The open primary sale intent can be executed using the token execute call, which will generate an execution plan for the primary sale.
The values in this examples are determined as follows:
Parameter | Description | Example |
---|---|---|
resourceId (in both asset term and instruction sections) | The asset being issued that has been distributed by the issuing organization | bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0 |
amount | The amount of tokens requests to be issued to the investor. This amount should not exceed the amount available in the open primary sale intent being executed | 10,000 |
finId | The finId of the investor who is requesting for the issuance of the tokens | 02d6fea8153a9a64d13e198379dfd4e a3945d03198770e0e5b94f556c4e69f6835 |
orgId | The organization id of the asset distributer (note this is not the organization id which the investor belongs to) | bank-uk |
custodian | The organization in charge of the custody service | custody-service |
amount | Amount in settlement section designates the funds stated in the given currency to transfer from investor to issuer account, which is the amount of tokens multiplied by the price per token as stated in the primary sale intent | 20,000 USD |
source finId | The investor finId at the payments organization which will have funds transfer from | 02d6fea8153a9a64d13e198379dfd4ea 3945d03198770e0e5b94f556c4e69f6835 |
destination finId | the issuer finId at the payments organization which will have the funds transfer to | 03565ed4e4d889ee24b7a6f830aa0df 31d7ba2ad88e9b1839d84c82de951397524 |
orgId | The payments organization Id | payment-service |
issuer | The owner registered id for the issuer | bank-uk:101:ff60289e-19f0-4f4c-a291-d587fb463999 |
buyer | The owner registered id for the buyer | bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144 |
user | The owner registered id for the buyer | bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144 |
intentId | The intent Id for the primary sale being executed | bank-uk:105:d07ab369-8bf2-4740-a055-1d11d2edfd38 |
exedcutionId | This is optional. You can either supply your own id, or if not supplied (do not include field in payload), id will be generated automatically. | 1234567890 |
curl --location --request POST 'http://<router url>/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data-raw '
{
"intentId": "bank-de:105:d07ab369-8bf2-4740-a055-1d11d2edfd38",
"user": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144",
"executionId": "1234567890",
"intent": {
"asset": {
"instruction": {
"destinationAccount": {
"account": {
"type": "finId",
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "bank-de",
"custodian": {
"orgId": "custodian-service"
}
},
"asset": {
"type": "finp2p",
"resourceId": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884"
}
}
},
"term": {
"asset": {
"type": "finp2p",
"resourceId": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884"
},
"amount": "10000"
}
},
"buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144",
"issuer": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
"nonce": "8a03fb05fcd070106d9f346b2abd86a7c72a0bf12acb30f2000000006734db5e",
"settlement": {
"term": {
"asset": {
"type": "fiat",
"code": "USD"
},
"amount": "20000"
},
"instruction": {
"destinationAccount": {
"asset": {
"type": "fiat",
"code": "USD"
},
"account": {
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payments-service",
"custodian": {
"orgId": "custodian-service"
},
"type": "finId"
}
},
"sourceAccount": {
"account": {
"type": "finId",
"orgId": "payments-service",
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"custodian": {
"orgId": "custodian-service"
}
},
"asset": {
"type": "fiat",
"code": "USD"
}
}
}
},
"type": "primarySaleExecution"
}
}
'
{
"isCompleted": true,
"response": {
"executionPlanId": "tomnext:106:1234567890"
},
"type": "execution"
}
Query for progress of execution plan against GraphQL:
Use GraphQL to poll for the progress of the execution plans being processed that your organization is participating in. Look for the execution plan id value of the plan you executed. Plan is finished either in a "completed" status, or "rejected" or "failed".
subscription planChanged{
plansChangedBy(fieldNames:Status) {
id
status
creationTimestamp
intent {id}
}
}
{
"data": {
"plansChangedBy": {
"id": "1234567890",
"status": "Completed",
"creationTimestamp": 1703495180,
"intent": {
"id": "bank-de:105:d07ab369-8bf2-4740-a055-1d11d2edfd38"
}
}
}
}
Example: Execute a Secondary Selling Intent
The following example is a walkthrough on how to send a request to execution against an open secondary selling intent posted by another investor:
Query for open secondary selling intents that are open for investment:
Query for open intents that are of type "sellingIntent" that have status of "ACTIVE". The intent information will provide you with the details required to execute the intent. The example shows an asset of a building that has 10,000 tokens available for investment valued at 3 USD each. The intent will be executed via the given payments processing organization "payments-service", during which asset tokens will be transferred from seller to buyer, while funds will be transferred from buyer to seller.
query OpenIntents {
assets {
nodes {
id
name
organizationId
issuerId
denomination {
code
}
certificates {
nodes {
data
documents {
nodes {
id
uri
}
}
}
}
intents(
filter: [{key: "type", operator: EQ, value: "secondaryIntent"}, {key: "status", operator: EQ, value: "ACTIVE"}]
) {
nodes {
id
type
start
end
status
remainingQuantity
intent {
... on PrimarySale {
issuerId
assetTerm {
amount
asset {
... on FinP2PAsset {
resourceId
}
}
}
assetInstruction {
account {
identifier {
... on FinP2PAssetAccount {
finId
orgId
custodian {
orgId
}
}
}
}
destinationAccount {
identifier {
... on FinP2PAssetAccount {
finId
orgId
custodian {
orgId
}
}
}
}
}
settlementTerm {
unitValue
asset {
... on FiatAsset {
code
}
}
}
sellingSettlementInstruction {
accounts {
identifier {
... on Iban {
code
}
... on FinP2PAssetAccount {
finId
orgId
}
}
}
}
}
}
}
}
}
}
}
{
"data": {
"assets": {
"nodes": [
{
"id": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884",
"name": "A-9499371996",
"organizationId": "bank-de",
"issuerId": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
"denomination": {
"code": "USD"
},
"certificates": {
"nodes": [
{
"data": "{\"publicName\":\"A-9499371996\",\"officialName\":\"Asset 9499371996, Inc\",\"description\":\"Asset 9499371996 description\",\"info\":[]}",
"documents": {
"nodes": [
{
"id": "6406e901-9ddf-404e-9222-71934cb36554",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/6406e901-9ddf-404e-9222-71934cb36554"
},
{
"id": "deb86f68-dc25-4d33-bfe6-83ff817cdd5c",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/deb86f68-dc25-4d33-bfe6-83ff817cdd5c"
},
{
"id": "9c405932-e894-4661-a15b-60802d3c782d",
"uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/9c405932-e894-4661-a15b-60802d3c782d"
}
]
}
},
{
"data": "{\"currentNAV\":{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140},\"history\":[{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140}]}",
"documents": {
"nodes": []
}
}
]
},
"intents": {
"nodes": []
}
}
]
}
}
}
Place a Secondary Sell Execution Request:
The open secondary selling intent can be executed using the token execute call, which will generate an execution plan for the secondary selling execution. In this case we are executing the full amount of tokens that was posted in the intent of 10,000.
The values in this examples are determined as follows:
Parameter | Description | Example |
---|---|---|
resourceId (in both asset term and instruction sections) | The asset being issued that has been distributed by the issuing organization | bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0 |
amount | The amount of tokens requests to be issued to the investor. This amount should not exceed the amount available in the open primary sale intent being executed | 10,000 |
source finId | The finId of the selling investor whose tokens will be transferred from | 02af7088141665f96ce1eb3db1bb2b4 5af58a8b3a09ee0dd64ee921e1b197fe2d5 |
orgId | The organization Id that is distributing the asset. | bank-uk |
destination finId | The finId of the buying investor who will be receiving the tokens. | 02d6fea8153a9a64d13e198379dfd4e a3945d03198770e0e5b94f556c4e69f6835 |
orgId | The organization Id that is distributing the asset. | bank-uk |
amount | Amount in settlement section designates the funds stated in the given currency to transfer from investor to issuer account, which is the amount of tokens multiplied by the price per token as stated in the secondary selling intent. | 30,000 USD |
source finId | the investor finId at the payments organization which will have funds transfer from | 02d6fea8153a9a64d13e198379dfd4ea 3945d03198770e0e5b94f556c4e69f6835 |
destination finId | the issuer finId at the payments organization which will have the funds transfer to | 02af7088141665f96ce1eb3db1bb2b4 5af58a8b3a09ee0dd64ee921e1b197fe2d5 |
orgId | The payments organization Id | payment-service |
buyer | The owner registered id for the buyer | bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144 |
user | The owner registered id for the buyer | bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144 |
intentId | The intent Id for the primary sale being executed | bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca |
signature | Follow the instruction for generating the proper signature to sign this given transaction. | 078e73c87b82183c9a2db2756098218a2d2409fed4b8 984d051f7c3b6ec1c94f6535e5b87db69d94d7ff0231ac 2ef58fd2a24f81a00e3e24da1d9667f4f5c58a |
exedcutionId | This is optional. You can either supply your own id, or if not supplied (do not include field in payload), id will be generated automatically. | 424d9d9c-7cd3-447b-840a-a3466a261423 |
custodian | the organization in charge of the custody services | custody-service |
curl --location 'http://<router url>/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data '
{
"intent": {
"type": "sellingIntentExecution",
"asset": {
"term": {
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
},
"amount": "4"
},
"instruction": {
"destinationAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "bank-uk"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
},
"sourceAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "simulation"
},
"finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
"orgId": "bank-uk"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
}
}
},
"settlement": {
"term": {
"asset": {
"type": "fiat",
"code": "USD"
},
"amount": "12"
},
"instruction": {
"sourceAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
},
"destinationAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "simulation"
},
"finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
}
}
},
"nonce": "0bf0068f05ea8eea6d340f386c42bf969322b97732d0b79e0000000000000000",
"buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
},
"intentId": "bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca",
"user": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
}
'
{
"isCompleted": true,
"response": {
"executionPlanId": "bank-uk:106:424d9d9c-7cd3-447b-840a-a3466a261423"
},
"type": ""
}
Query for progress of execution plan:
Use GraphQL to poll for the progress of the execution plans being processed that your organization is participating in. Look for the execution plan id value of the plan you executed. Plan is finished either in a "completed" status, or "rejected" or "failed".
subscription planChanged{
plansChangedBy(fieldNames:Status) {
id
status
creationTimestamp
intent {id}
}
}
{
"data": {
"plansChangedBy": {
"id": "424d9d9c-7cd3-447b-840a-a3466a261423",
"status": "Completed",
"creationTimestamp": 1703495180,
"intent": {
"id": "bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca"
}
}
}
}
Example: Post a Selling or Buying Intent and Processing Execution Request
Post a Secondary Selling Intent:
The investor can post a secondary intent that can is broadcasted to all shared parties. Once an execution request is placed by another investor (during which it is signed by the investor), the token transfer request will be routed to the tokenization platform of the asset to approve or reject the execution. If and once approved, the execution will be sent to be signed by the creator of the intent.
The example below is posting a secondary selling intent for 5,000 units of the token valued at 4 USD a token. The intent is set to be manually signed upon execution of the intent by the set end point.
Note you need to specify an expiry value for a buying intent only. Do not supply it in a selling intent as it is a capability for the buyer to indicate how long they intent on having their funds held for the transaction to occur.
curl --location --request POST 'http://<router url>/finapi/profiles/asset/bank-us:102:234b2028-6362-40fe-bb0c-f71668c08639/intent' \
--header 'Content-Type: application/json' \
--data-raw '{
"intent": {
"type": "sellingIntent",
"assetTerm": {
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
},
"amount": "5000"
},
"assetInstruction": {
"account": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "bank-us"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
}
},
"settlementTerm": {
"asset": {
"type": "fiat",
"code": "USD"
},
"unitValue": "4"
},
"settlementInstruction": {
"destinationAccounts": [
{
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
}
]
},
"signaturePolicy": {
"type": "manualPolicy"
},
"seller": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
},
"start": 1719927761,
"end": 1719927761
}'
curl --location --request POST 'http://<router url>/finapi/profiles/asset/bank-us:102:234b2028-6362-40fe-bb0c-f71668c08639/intent' \
--header 'Content-Type: application/json' \
--data-raw '
{
"intent": {
"type": "buyingIntent",
"assetTerm": {
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
},
"amount": "5000"
},
"assetInstruction": {
"account": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "simulation"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
}
},
"settlementTerm": {
"asset": {
"type": "fiat",
"code": "USD"
},
"unitValue": "4"
},
"settlementInstruction": {
"sourceAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
}
},
"signaturePolicy": {
"type": "manualPolicy"
},
"buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
},
"start": 1720090595,
"end": 1720090595
}
'
{
"id": "bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c"
}
You can disable/enable the intent for the given asset using the Intent ID
curl --location --request PUT 'http://<router url>/finapi/profiles/asset/bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0/intent/bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c/disable' \
--header 'Content-Type: application/json' \
--data-raw ''
Example: Posting and Executing a Repo/Loan Intent
The following is an example of posting a repo/loan type of an intent, which is executed on behalf of the borrower and lender that have pre-negotiated the terms of the intent.
In this case the borrower and the lender are executing the following repo trade:
Description | Example |
---|---|
openDate | Indicates in Epoch GMT when the settlement leg will be initiated. |
closeDate | Indicates in Epoch GMT when the maturity leg will be initiated. |
unitValue | Indicates the amount that is being borrowed in the repo trade. |
repaymentVolume | Indicates the amount that will be returned back to the lender at Maturity, which includes the interest payment. |
interestRate | Indicates the interest % (in basis points) that was used to calculate the amount at maturity. |
curl --location --request POST 'http://nodeurl/finapi/profiles/asset/<assetId>/intent' \
--header 'Content-Type: application/json' \
--data-raw '{
"start": 1684669145,
"end": 1684669745,
"assetTerm": {
"asset": {
"type": "finp2p",
"resourceId": "<assetId>"
},
"amount": "1"
},
"assetInstruction": {
"account": {
"asset": {
"type": "finp2p",
"resourceId": <assetId>"
},
"account": {
"type": "finId",
"finId": "<borrower FinID>",
"orgId": "<collateral orgId>"
}
}
},
"settlementTerm": {
"asset": {
"type": "fiat",
"code": "USD"
},
"unitValue": "2000000"
},
"intent": {
"type": "loanIntent",
"creatorType": "borrower",
"lender": "<Lender Resource ID>",
"borrower": "<Borrower Resource ID>",
"settlementInstruction": {
"type": "escrow",
"borrowerAccount": {
"asset": {
"type": "fiat",
"code": "USD"
},
"account": {
"type": "finId",
"finId": "<borrower finID>",
"orgId": "<payment orgId>"
}
},
"lenderAccount": {
"asset": {
"type": "fiat",
"code": "USD"
},
"account": {
"type": "finId",
"finId": "<lender finID>",
"orgId": "<payment orgId>"
}
}
},
"loanInstruction": {
"openDate": 1687867856,
"closeDate": 1687867886,
"conditions": {
"type": "repaymentTerm",
"repaymentVolume": "2002054.79",
"interestRate": "10"
}
},
"signaturePolicy": {
"type": "presignedPolicy"
}
}
}'
{
"id": "bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c"
}
Execute the Intent:
curl --location --request POST 'http://nodeurl/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data-raw '{
"intentId": "bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c"",
“executionId”: 12345678
"intent": {
"type": "loanIntentExecution",
"executorType": "lender",
"nonce": "77c1efde5ad0cf3cb49e4c405331aefe3eb721cda7298fe000000000646a013e",
"borrower": "<Borrower Resource ID>",
"lender": "<Lender Resource ID>",
"asset": {
"term": {
"asset": {
"type": "finp2p",
"resourceId": "<assetId>"
},
"amount": "1"
},
"instruction": {
"sourceAccount": {
"asset": {
"type": "finp2p",
"resourceId": "<assetId>"
},
"account": {
"type": "finId",
"finId": "<borrower finID>",
"orgId": "<collateral orgId>"
}
},
"destinationAccount": {
"asset": {
"type": "finp2p",
"resourceId": "<assetId>"
},
"account": {
"type": "finId",
"finId": "<lender finID>",
"orgId": "<collateral orgId>"
}
}
}
},
"settlement": {
"term": {
"asset": {
"type": "fiat",
"code": "USD"
},
"amount": "2000000"
},
"instruction": {
"sourceAccount": {
"asset": {
"type": "fiat",
"code": "USD"
},
"account": {
"type": "finId",
"finId": "<lender FinID>",
"orgId": "<payments orgId>"
}
},
"destinationAccount": {
"asset": {
"type": "fiat",
"code": "USD"
},
"account": {
"type": "finId",
"finId": "<borrower FinID>",
"orgId": "<payments orgId>"
}
},
"type": "escrow"
}
},
"loanInstruction": {
"openDate": 1687867856,
"closeDate": 1687867886,
"conditions": {
"type": "repaymentTerm",
"closeAmount": "2002054.79",
"interestRate": "10"
}
}
}
}'
{
"id": "bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c"
}
Example: Execute a Redeem
The following is an example of an execution request for a redeem intent:
curl --location 'http://<router url>/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data '
{
"intent": {
"type": "sellingIntentExecution",
"asset": {
"term": {
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
},
"amount": "4"
},
"instruction": {
"destinationAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "bank-uk"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
},
"sourceAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "simulation"
},
"finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
"orgId": "bank-uk"
},
"asset": {
"type": "finp2p",
"resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
}
}
}
},
"settlement": {
"term": {
"asset": {
"type": "fiat",
"code": "USD"
},
"amount": "12"
},
"instruction": {
"sourceAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "custody-service"
},
"finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
},
"destinationAccount": {
"account": {
"type": "finId",
"custodian": {
"orgId": "simulation"
},
"finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
"orgId": "payment-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
}
}
},
"nonce": "0bf0068f05ea8eea6d340f386c42bf969322b97732d0b79e0000000000000000",
"buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
},
"intentId": "bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca",
"user": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
}
'
{
"isCompleted": true,
"response": {
"executionPlanId": "bank-uk:106:424d9d9c-7cd3-447b-840a-a3466a261423"
},
"type": ""
}
Example: Request Funds Withdrawal
Send a withdrawal request to payment service organization
Include in the description the text or object required by the payments organization in order to process the withdrawal.
curl --location --request POST 'https://<router_url>/finapi/payments/withdraw' \
--header 'Content-Type: application/json' \
--data-raw '{
"profileId": "bank-uk:101:f2ee5840-8b7d-47ae-a4dc-ee9d02b0cee8",
"account": {
"account": {
"type": "finId",
"finId": "037fcf0db48dceb2195bd0fc24a4dab68c5731b5b8c141f63d017969a55570c4e9",
"orgId": "payments-service"
},
"asset": {
"type": "fiat",
"code": "USD"
}
},
"amount": "10000",
"withdrawInstruction": {
"account": {
"account": {
"type": "iban",
"code": "GB33BUKB20201555555555"
},
"asset": {
"type": "fiat",
"code": "USD"
}
},
"description": "Withdrawal instructions"
}
}'
{
"cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
"isCompleted": false,
"type": "withdraw"
}
Poll to receive the status of the withdrawal request processing
curl --location --request POST 'https://<router_url>/finapi//operations/status/45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d"' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
"cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
"isCompleted": false,
"type": "withdraw"
}
{
"cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
"isCompleted": true,
"type": "withdraw"
}
{
"type": "receipt",
"operation": {
"cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
"isCompleted": true,
"error": {
"Code":30,
"Message": "Withdrawal operation failed"
}
}
}
Updated about 1 month ago