Placing dShare Orders
Before an Entity can place a dShare order, make sure it fulfills the following pre-requisites:
- Entity has a valid KYC
- Entity has a valid account
- Entity has enough funds
Ordering using the API SDK
This is only usable by Accounts with a Dinari-managed wallet
import Dinari from '@dinari/api-sdk';
const client = new Dinari({
apiKeyID: process.env['DINARI_API_KEY_ID'], // This is the default and can be omitted
apiSecretKey: process.env['DINARI_API_SECRET_KEY'], // This is the default and can be omitted
environment: 'sandbox', // defaults to 'production'
});
async function main() {
const accountID = 'your-account-id';
const stockID = 'your-stock-id';
// Limit Buy Order
const limitBuy = await client.v2.accounts.orderRequests.createLimitBuy(accountID, {
asset_quantity: 1,
limit_price: 1.5,
stock_id: stockID,
});
console.log('Limit Buy Response:', limitBuy);
// Limit Sell Order
const limitSell = await client.v2.accounts.orderRequests.createLimitSell(accountID, {
asset_quantity: 1,
limit_price: 1.5,
stock_id: stockID,
});
console.log('Limit Sell Response:', limitSell);
// Market Buy Order
const marketBuy = await client.v2.accounts.orderRequests.createMarketBuy(accountID, {
stock_id: stockID,
payment_amount: 150.0,
});
console.log('Market Buy Response:', marketBuy);
// Market Sell Order
const marketSell = await client.v2.accounts.orderRequests.createMarketSell(accountID, {
stock_id: stockID,
asset_quantity: 1,
});
console.log('Market Sell Response:', marketSell);
}
main();import os
from dinari_api_sdk import Dinari
client = Dinari(
api_key_id=os.environ.get("DINARI_API_KEY_ID"), # This is the default and can be omitted
api_secret_key=os.environ.get("DINARI_API_SECRET_KEY"), # This is the default and can be omitted
environment="sandbox", # defaults to "production"
)
account_id = "your-account-id"
stock_id = "your-stock-id"
# Limit Buy Order
limit_buy = client.v2.accounts.order_requests.create_limit_buy(
account_id=account_id,
asset_quantity=1,
limit_price=1.5,
stock_id=stock_id,
)
# Limit Sell Order
limit_sell = client.v2.accounts.order_requests.create_limit_sell(
account_id=account_id,
asset_quantity=1,
limit_price=1.5,
stock_id=stock_id,
)
# Market Buy Order
market_buy = client.v2.accounts.order_requests.create_market_buy(
account_id=account_id,
stock_id=stock_id,
payment_amount=150.0,
)
# Market Sell Order
market_sell = client.v2.accounts.order_requests.create_market_sell(
account_id=account_id,
stock_id=stock_id,
asset_quantity=1,
)package main
import (
"context"
"fmt"
"log"
dinari "github.com/dinaricrypto/dinari-api-sdk-go"
"github.com/dinaricrypto/dinari-api-sdk-go/option"
)
func main() {
// DINARI_API_KEY_ID and DINARI_API_SECRET_KEY are set as environment variables
client := dinari.NewClient(
option.WithEnvironmentSandbox(), // Defaults to production when omitted
)
accountID := "your-account-id"
stockID := "your-stock-id"
// Limit Buy Order
limitBuyResp, err := client.V2.Accounts.OrderRequests.NewLimitBuy(context.TODO(), accountID, dinari.V2AccountOrderRequestNewLimitBuyParams{
CreateLimitOrderInput: dinari.CreateLimitOrderInputParam{
AssetQuantity: 1,
LimitPrice: 1.5,
StockID: stockID,
},
})
if err != nil {
log.Fatalf("Failed to create limit buy order: %v", err)
}
fmt.Printf("Limit Buy Response: %+v\n", limitBuyResp)
// Limit Sell Order
limitSellResp, err := client.V2.Accounts.OrderRequests.NewLimitSell(context.TODO(), accountID, dinari.V2AccountOrderRequestNewLimitSellParams{
CreateLimitOrderInput: dinari.CreateLimitOrderInputParam{
AssetQuantity: 1,
LimitPrice: 1.5,
StockID: stockID,
},
})
if err != nil {
log.Fatalf("Failed to create limit sell order: %v", err)
}
fmt.Printf("Limit Sell Response: %+v\n", limitSellResp)
// Market Buy Order
marketBuyResp, err := client.V2.Accounts.OrderRequests.NewMarketBuy(context.TODO(), accountID, dinari.V2AccountOrderRequestNewMarketBuyParams{
PaymentAmount: 150.0, // This is the dollar amount to spend
StockID: stockID,
})
if err != nil {
log.Fatalf("Failed to create market buy order: %v", err)
}
fmt.Printf("Market Buy Response: %+v\n", marketBuyResp)
// Market Sell Order
marketSellResp, err := client.V2.Accounts.OrderRequests.NewMarketSell(context.TODO(), accountID, dinari.V2AccountOrderRequestNewMarketSellParams{
AssetQuantity: 1,
StockID: stockID,
})
if err != nil {
log.Fatalf("Failed to create market sell order: %v", err)
}
fmt.Printf("Market Sell Response: %+v\n", marketSellResp)
}Ordering using a Smart Contract
EVM
User Sponsored (sdk v0.6.0)
import os
from dinari_api_sdk import Dinari
from eth_account import Account
from eth_account.messages import encode_typed_data
client = Dinari(
api_key_id=os.environ.get("DINARI_API_KEY_ID"), # This is the default and can be omitted
api_secret_key=os.environ.get("DINARI_API_SECRET_KEY"), # This is the default and can be omitted
environment="sandbox", # defaults to "production"
)
account_id = "your-account-id"
# Step 1. Create permit
resp = client.v2.accounts.order_requests.eip155.create_permit(
account_id,
chain_id="eip155:11155111",
order_side="BUY",
order_tif="DAY",
order_type="MARKET",
payment_token="0xC6E13d97d73721ecA623F6d6c77ceBAFD2fF6431",
payment_token_quantity=1.5,
stock_id=stock_id,
)
# Step 2. Sign permit
private_key = "your-wallet-private-key"
acct = Account.from_key(private_key)
message = encode_typed_data(full_message=resp.permit)
signature = acct.sign_message(message).signature
# Step 3. Create permit transaction
tx_resp = client.v2.accounts.order_requests.eip155.create_permit_transaction(
account_id,
order_request_id=resp.order_request_id,
permit_signature="0x" + signature.hex(),
)
# Step 4. Sign and send transaction
w3 = Web3(HTTPProvider("localhost:8545"))
tx = {
"to": tx_resp.contract_address,
"data": tx_resp.data,
"value": tx_resp.value,
"gas": w3.eth.estimate_gas(
{
"from": acct.address,
"to": tx_resp.contract_address,
"data": HexStr(tx_resp.data),
"value": Wei(int(tx_resp.value)),
}
),
"gasPrice": w3.eth.gas_price,
"nonce": w3.eth.get_transaction_count(acct.address),
"chainId": 421614, # e.g. Arbitrum Sepolia
}
signed = acct.sign_transaction(tx)
txHash = w3.eth.send_raw_transaction(signed.rawTransaction)
import { V2 } from "@dinari/api-sdk/resources/index";
import * as AccountsAPI from "@dinari/api-sdk/resources/v2/accounts";
import {
WalletClient,
Address,
Account,
createWalletClient,
createPublicClient,
http,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
import { Eip155CreatePermitResponse } from "@dinari/api-sdk/resources/v2/accounts/order-requests";
export async function signPermitMessageForViem(
walletClient: WalletClient,
permit: NonNullable<Eip155CreatePermitResponse["permit"]>,
account?: Account,
): Promise<`0x${string}`> {
if (
!permit?.domain ||
!permit?.types ||
!permit?.message ||
!permit?.primaryType
) {
throw new Error("permit is missing required fields");
}
let resolvedAccount: Address | Account;
if (account) {
resolvedAccount = account;
} else {
[resolvedAccount] = await walletClient.requestAddresses();
}
// The permit is already in the correct shape (domain, types, primaryType, message)
// In Python: encode_typed_data(full_message=resp.permit) then sign_message(message)
// But since we're using viem, we can just sign the typed data directly
// which handles the encoding and signing in one step
const signature = await walletClient.signTypedData({
account: resolvedAccount,
domain: permit.domain as any,
types: permit.types as any,
primaryType: (permit.primaryType ?? "") as string,
message: permit.message as any,
});
return signature;
}
export async function userSponsored(client: V2, accountId: string) {
const stocks = await client.marketData.stocks.list();
const stockId = stocks[0].id;
// Replace with your chain ID (e.g., "eip155:421614" for Arbitrum Sepolia)
const caip2ChainId: AccountsAPI.Chain =
(process.env.PROXIED_CHAIN_ID as AccountsAPI.Chain) ?? "eip155:1337";
const permitResponse: Eip155CreatePermitResponse =
await client.accounts.orderRequests.eip155.createPermit(accountId, {
chain_id: caip2ChainId,
order_side: "BUY",
order_tif: "DAY",
order_type: "MARKET",
stock_id: stockId,
// Replace with your payment token address
payment_token: process.env.PAYMENT_TOKEN || "",
payment_token_quantity: 1.5,
});
// Replace with your private key (without 0x prefix)
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);
const rpcUrl = "https://sepolia-rollup.arbitrum.io/rpc";
const walletClient = createWalletClient({
account,
chain: arbitrumSepolia,
transport: http(rpcUrl),
});
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(rpcUrl),
});
// Step 2. Sign the permit
const permitSignature = await signPermitMessageForViem(
walletClient,
permitResponse.permit,
account,
);
// Step 3. Create permit transaction
const transactionResponse =
await client.accounts.orderRequests.eip155.createPermitTransaction(
accountId,
{
order_request_id: permitResponse.order_request_id,
permit_signature: permitSignature,
},
);
// Step 4. Send the transaction
}
async function main() {
const client = new Dinari({
apiKeyID: process.env["DINARI_API_KEY_ID"],
apiSecretKey: process.env["DINARI_API_SECRET_KEY_ID"],
});
await userSponsored(client.v2, "your_account_id");
}package main
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"github.com/chenzhijie/go-web3"
dinari "github.com/dinaricrypto/dinari-api-sdk-go"
"github.com/dinaricrypto/dinari-api-sdk-go/option"
"github.com/dinaricrypto/dinari-api-sdk-go/packages/param"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
)
func main() {
// DINARI_API_KEY_ID and DINARI_API_SECRET_KEY are set as environment variables
client := dinari.NewClient(
option.WithEnvironmentSandbox(), // Defaults to production when omitted
)
accountID := "your account id"
ctx := context.TODO()
prepareOrderBody := dinari.V2AccountOrderRequestEip155NewPermitParams{
ChainID: dinari.ChainEip155_421614,
OrderSide: dinari.OrderSideBuy,
OrderTif: dinari.OrderTifDay,
OrderType: dinari.OrderTypeMarket,
StockID: param.Opt[string]{Value: "0196d545-d8a8-7210-8cd1-a49e82c31e53"},
PaymentToken: "0x6a34FDFE60D1758dF5b577d413E37397D21c3E78",
PaymentTokenQuantity: dinari.Float(1.5),
}
// Step 1. Create the order permit
permitResp, err := client.V2.Accounts.OrderRequests.Eip155.NewPermit(ctx, accountID, prepareOrderBody)
if err != nil {
log.Fatalf("Failed: %v", err)
}
fmt.Printf("hashes: %+v\n", permitResp.Permit["types"])
var rpcProviderURL = "https://sepolia-rollup.arbitrum.io/rpc"
w3, err := web3.NewWeb3(rpcProviderURL)
if err != nil {
panic(err)
}
w3.Eth.SetChainId(421614)
// Step 2. Sign the permit
privateKeyHex := "your private key"
err = w3.Eth.SetAccount(privateKeyHex)
if err != nil {
panic(err)
}
permit := permitResp.Permit
var types apitypes.Types
var domain apitypes.TypedDataDomain
var message apitypes.TypedDataMessage
typesJSON, err := json.Marshal(permit["types"])
if err != nil {
log.Fatalf("failed to marshal types: %v", err)
}
if err := json.Unmarshal(typesJSON, &types); err != nil {
log.Fatalf("failed to unmarshal types: %v", err)
}
domainJSON, err := json.Marshal(permit["domain"])
if err != nil {
log.Fatalf("failed to marshal domain: %v", err)
}
if err := json.Unmarshal(domainJSON, &domain); err != nil {
log.Fatalf("failed to unmarshal domain: %v", err)
}
messageJSON, err := json.Marshal(permit["message"])
if err != nil {
log.Fatalf("failed to marshal message: %v", err)
}
if err := json.Unmarshal(messageJSON, &message); err != nil {
log.Fatalf("failed to unmarshal message: %v", err)
}
permitTypedData := apitypes.TypedData{
Types: types,
PrimaryType: permit["primaryType"].(string),
Domain: domain,
Message: message,
}
signedPermit, err := w3.Eth.SignTypedData(permitTypedData)
if err != nil {
log.Fatalf("failed sign typed data: %v", err)
}
signedPermitHexString := fmt.Sprintf("0x%s", hex.EncodeToString(signedPermit))
fmt.Printf("signedPermit: %s\n", signedPermitHexString)
// Step 3. Create the transaction
permitTransactionBody := dinari.V2AccountOrderRequestEip155NewPermitTransactionParams{
OrderRequestID: permitResp.OrderRequestID,
PermitSignature: signedPermitHexString,
}
permitTransaction, err := client.V2.Accounts.OrderRequests.Eip155.NewPermitTransaction(ctx, accountID, permitTransactionBody)
if err != nil {
log.Fatalf("failed to create permit transaction: %v", err)
}
fmt.Printf("signedPermit: %+v\n", permitTransaction)
// Step 4. Send the transaction
}
Dinari sponsored (sdk v0.6.0)
import os
from dinari_api_sdk import Dinari
from eth_account import Account
from eth_account.messages import encode_typed_data
client = Dinari(
api_key_id=os.environ.get("DINARI_API_KEY_ID"), # This is the default and can be omitted
api_secret_key=os.environ.get("DINARI_API_SECRET_KEY"), # This is the default and can be omitted
environment="sandbox", # defaults to "production"
)
account_id = "your-account-id"
# Step 1. Create permit
resp = client.v2.accounts.order_requests.eip155.create_permit(
account_id,
chain_id="eip155:11155111",
order_side="BUY",
order_tif="DAY",
order_type="MARKET",
payment_token="0xC6E13d97d73721ecA623F6d6c77ceBAFD2fF6431",
payment_token_quantity=1.5,
stock_id=stock_id,
)
# Step 2. Sign permit
private_key = "your-wallet-private-key"
acct = Account.from_key(private_key)
message = encode_typed_data(full_message=resp.permit)
signature = acct.sign_message(message).signature
# Step 3. Submit permit signature to Dinari
submit_resp = client.v2.accounts.order_requests.eip155.submit(
account_id,
order_request_id=resp.order_request_id,
permit_signature="0x" + signature.hex(),
)
import { V2 } from "@dinari/api-sdk/resources/index";
import * as AccountsAPI from "@dinari/api-sdk/resources/v2/accounts";
import {
WalletClient,
Address,
Account,
createWalletClient,
createPublicClient,
http,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
import { Eip155CreatePermitResponse } from "@dinari/api-sdk/resources/v2/accounts/order-requests";
export async function signPermitMessageForViem(
walletClient: WalletClient,
permit: NonNullable<Eip155CreatePermitResponse["permit"]>,
account?: Account,
): Promise<`0x${string}`> {
if (
!permit?.domain ||
!permit?.types ||
!permit?.message ||
!permit?.primaryType
) {
throw new Error("permit is missing required fields");
}
let resolvedAccount: Address | Account;
if (account) {
resolvedAccount = account;
} else {
[resolvedAccount] = await walletClient.requestAddresses();
}
const signature = await walletClient.signTypedData({
account: resolvedAccount,
domain: permit.domain as any,
types: permit.types as any,
primaryType: (permit.primaryType ?? "") as string,
message: permit.message as any,
});
return signature;
}
export async function dinariSponsored(client: V2, accountId: string) {
const stocks = await client.marketData.stocks.list();
const stockId = stocks[0].id;
// Replace with your chain ID (e.g., "eip155:421614" for Arbitrum Sepolia)
const caip2ChainId: AccountsAPI.Chain =
(process.env.PROXIED_CHAIN_ID as AccountsAPI.Chain) ?? "eip155:1337";
const permitResponse: Eip155CreatePermitResponse =
await client.accounts.orderRequests.eip155.createPermit(accountId, {
chain_id: caip2ChainId,
order_side: "BUY",
order_tif: "DAY",
order_type: "MARKET",
stock_id: stockId,
// Replace with your payment token address
payment_token: process.env.PAYMENT_TOKEN || "",
payment_token_quantity: 1.5,
});
// Replace with your private key (without 0x prefix)
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);
const rpcUrl = "https://sepolia-rollup.arbitrum.io/rpc";
const walletClient = createWalletClient({
account,
chain: arbitrumSepolia,
transport: http(rpcUrl),
});
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(rpcUrl),
});
// Step 2. Sign the permit
const permitSignature = await signPermitMessageForViem(
walletClient,
permitResponse.permit,
account,
);
// Step 3. Submit order through Dinari
const transactionResponse =
await client.accounts.orderRequests.eip155.submit(
accountId,
{
order_request_id: permitResponse.order_request_id,
permit_signature: permitSignature,
},
);
}
async function main() {
const client = new Dinari({
apiKeyID: process.env["DINARI_API_KEY_ID"],
apiSecretKey: process.env["DINARI_API_SECRET_KEY_ID"],
});
await dinariSponsored(client.v2, "your_account_id");
}package main
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"github.com/chenzhijie/go-web3"
dinari "github.com/dinaricrypto/dinari-api-sdk-go"
"github.com/dinaricrypto/dinari-api-sdk-go/option"
"github.com/dinaricrypto/dinari-api-sdk-go/packages/param"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
)
func main() {
// DINARI_API_KEY_ID and DINARI_API_SECRET_KEY are set as environment variables
client := dinari.NewClient(
option.WithEnvironmentSandbox(), // Defaults to production when omitted
)
accountID := "your account id"
ctx := context.TODO()
prepareOrderBody := dinari.V2AccountOrderRequestEip155NewPermitParams{
ChainID: dinari.ChainEip155_421614,
OrderSide: dinari.OrderSideBuy,
OrderTif: dinari.OrderTifDay,
OrderType: dinari.OrderTypeMarket,
StockID: param.Opt[string]{Value: "0196d545-d8a8-7210-8cd1-a49e82c31e53"},
PaymentToken: "0x6a34FDFE60D1758dF5b577d413E37397D21c3E78",
PaymentTokenQuantity: dinari.Float(1.5),
}
// Step 1. Create the order permit
permitResp, err := client.V2.Accounts.OrderRequests.Eip155.NewPermit(ctx, accountID, prepareOrderBody)
if err != nil {
log.Fatalf("Failed: %v", err)
}
fmt.Printf("hashes: %+v\n", permitResp.Permit["types"])
var rpcProviderURL = "https://sepolia-rollup.arbitrum.io/rpc"
w3, err := web3.NewWeb3(rpcProviderURL)
if err != nil {
panic(err)
}
w3.Eth.SetChainId(421614)
// Step 2. Sign the permit
privateKeyHex := "your private key"
err = w3.Eth.SetAccount(privateKeyHex)
if err != nil {
panic(err)
}
permit := permitResp.Permit
var types apitypes.Types
var domain apitypes.TypedDataDomain
var message apitypes.TypedDataMessage
typesJSON, err := json.Marshal(permit["types"])
if err != nil {
log.Fatalf("failed to marshal types: %v", err)
}
if err := json.Unmarshal(typesJSON, &types); err != nil {
log.Fatalf("failed to unmarshal types: %v", err)
}
domainJSON, err := json.Marshal(permit["domain"])
if err != nil {
log.Fatalf("failed to marshal domain: %v", err)
}
if err := json.Unmarshal(domainJSON, &domain); err != nil {
log.Fatalf("failed to unmarshal domain: %v", err)
}
messageJSON, err := json.Marshal(permit["message"])
if err != nil {
log.Fatalf("failed to marshal message: %v", err)
}
if err := json.Unmarshal(messageJSON, &message); err != nil {
log.Fatalf("failed to unmarshal message: %v", err)
}
permitTypedData := apitypes.TypedData{
Types: types,
PrimaryType: permit["primaryType"].(string),
Domain: domain,
Message: message,
}
signedPermit, err := w3.Eth.SignTypedData(permitTypedData)
if err != nil {
log.Fatalf("failed sign typed data: %v", err)
}
signedPermitHexString := fmt.Sprintf("0x%s", hex.EncodeToString(signedPermit))
fmt.Printf("signedPermit: %s\n", signedPermitHexString)
// Step 3. Submit the order through Dinari
submitBody := dinari.V2AccountOrderRequestEip155SubmitParams{
OrderRequestID: permitResp.OrderRequestID,
PermitSignature: signedPermitHexString,
}
submitResponse, err := client.V2.Accounts.OrderRequests.Eip155.Submit(ctx, accountID, submitBody)
if err != nil {
log.Fatalf("failed to submit order: %v", err)
}
fmt.Printf("signedPermit: %+v\n", submitResponse)
}
Updated 12 days ago