Placing dShare Orders

Before an Entity can place a dShare order, make sure it fulfills the following pre-requisites:

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)

}