nibiruchain / py-sdk Goto Github PK
View Code? Open in Web Editor NEWPython-based client for interacting with the Nibiru blockchain
License: MIT License
Python-based client for interacting with the Nibiru blockchain
License: MIT License
Poetry is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
poetry
edits dependencies directly in the pyproject.toml and works well for versioning and publishing.
perp commands:
tx perp open-position
and its responsetx perp close-position
and its responsetx perp add-margin
tx perp remove-margin
other commands:
tx pricefeed
tx bank
else:
Running the trading bot for 20 minutes or more leads to this:
trading_bot | ERROR:root:Failed tx execution: failed to simulate tx : <AioRpcError of RPC that terminated with:
trading_bot | status = StatusCode.UNKNOWN
trading_bot | details = "account sequence mismatch, expected 73, got 61: incorrect account sequence"
trading_bot | debug_error_string = "{"created":"@1657809272.661877125","description":"Error received from peer ipv4:192.168.65.2:9090","file":"src/core/lib/surface/call.cc","file_line":966,"grpc_message":"account sequence mismatch, expected 73, got 61: incorrect account sequence","grpc_status":2}"
This error seems to be repeating and i'm sending one transaction per account every 10 seconds.
Driven by Heart Monitor feature to track Module account balances.
So, we need to integrate this command in SDK:
nibid q auth accounts --node tcp://34.130.24.87:26657 --chain-id nibiru-localnet-0 | jq
{
"accounts": [
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1qqx5reauy4glpskmppy88pz25qp2py5yxvpxdt",
"pub_key": null,
"account_number": "4",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1qc0wrpj2tc2feduz5qewpncxkcpx9uh90hfmy6",
"pub_key": null,
"account_number": "89",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1p5r8pfzpscmzh9dj5np6gnz3pzd6an96u49etg",
"pub_key": null,
"account_number": "55",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1p4evtasvvt5zgvkm4j9altq245lt7qu68e8kav",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AheNUQJwk7dItmOkTFIXWQ2AQJGht7yd0uFtmaqv/4Iw"
},
"account_number": "33",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1phtvz445sp37n59sa8rk5l066t36wpkvs7f5js",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Am2f4OMyU5EuEw4sFU5D4NvEGOVwgKrRCsJszdLardAb"
},
"account_number": "67",
"sequence": "3350"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1zaavvzxez0elundtn32qnk9lkm8kmcsz44g7xl",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AvzwBOriY8sVwEXrXf1gXanhT9imlfWeUWLQ8pMxrRsg"
},
"account_number": "6",
"sequence": "256"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1rp8m0qeusugw3za2gcnwq8f800mlru92lh2knh",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AnLZZEU1Lx918iG8iX/958CsXqT6OWHzH+aeT6W4I0mF"
},
"account_number": "42",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1rj9rs48vk99d6avslr7njh9zuacnlegx2twnfu",
"pub_key": null,
"account_number": "50",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1rkl39aqdqwd23seugmqyn86dcwytljav6qdq0v",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A3SjZ9ZRZ3vB1WnUUpN/k0Pg6ZgefQIUMgtJYvf83oU/"
},
"account_number": "78",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1y5sq69lul8384xff4maa8gt6g9a4p8vf40kk4w",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AmJaJceOGfT2WfgzcAj4mdn978T3MXgQW17LA8L0iIZI"
},
"account_number": "17",
"sequence": "52"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1yl6hdjhmkf37639730gffanpzndzdpmhe6js7s",
"pub_key": null,
"account_number": "16",
"sequence": "0"
},
"name": "transfer",
"permissions": [
"minter",
"burner"
]
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi195nql46v0q45f57gyvtnztmdjvxtd3verjx6hg",
"pub_key": null,
"account_number": "64",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1xqt90ztndjgv82k00ee2ua5grwt7hhkp90pyge",
"pub_key": null,
"account_number": "19",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1x02z93f4tphv32t3v7dn85vswclj7z662m5pgn",
"pub_key": null,
"account_number": "93",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1xnmldph4jlphcr6ehkvpktmnuzs5dhug5q94vv",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AgJcdikrmMRU/dyNejyFjUTDbhywF5JN4qTq8ZQUUchr"
},
"account_number": "106",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1x5zknk8va44th5vjpg0fagf0lxx0rvurpmp8gs",
"pub_key": null,
"account_number": "5",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1xc03tjdlsz6cukwpgp4wn0ampcawfn7refkdah",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AsKsA0S60M2HMzL/dbZZSZ7+kqhOJA5gQr5Nc0LkA9jF"
},
"account_number": "100",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1xmklmz3gpv6lkr5p4vr6dvvxflq62mzn6lw8x0",
"pub_key": null,
"account_number": "77",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi18rttg39wc3j5lm5u5hptpmlte5tdmz6s39zcw3",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AzMHI2I/f7nLgfjdcHaAKFP7i2wh0nimhiqvlLReo5SA"
},
"account_number": "69",
"sequence": "4671"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi18dqe39j4jl96cjqcpp2keclhgwh6ulvuq9008a",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Ammz3Dhbt3SX6djQgSGZqUeXnOAr6nDckdyzsjBp/yYm"
},
"account_number": "88",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi18sh9t48mfm2vpn5mt9mkg64rsss7gtyq0ppuq7",
"pub_key": null,
"account_number": "29",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi185qxlmdm7tsmryfptdv7whd2zhrxecrmmn02xu",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A+mRaUFz/BaO1Lyj9k69g9CQ4n3MhXDDYAS5gE4GLsnb"
},
"account_number": "82",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi18mwuuf6n0kxkw6z7euhuvq9plud582nj7xnd27",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AnsqJKaRjvpOJpGonnNSgRd6F6rg9EAZjOZY6cir9Xnv"
},
"account_number": "97",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1gxgq9fkdq8505thtnq9w4c7v9vgvh30qpfht3c",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Ah5PQIoeMQ+NwdlWQ7FT3jwUo3GL60ahMUbKpPMIzmzN"
},
"account_number": "91",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1g2xyc2qs85v8jlpvd0r6hsu4ehxl5ws3ttc0e7",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Au5aJ9yFMNTJdBpDIyiKG4gBxfLQICnEIKVeac9UL1dA"
},
"account_number": "20",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1g4694cyysj3836tmhylgdyesql393rv8fgmv3x",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Ar2S00+/oX9UY6ISF/sBNt3Gfyh8U5PNLhzklhOy56FS"
},
"account_number": "107",
"sequence": "2"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1glugnk8xfysrh0vdy2fghkv9yagyclfuccxvc6",
"pub_key": null,
"account_number": "56",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1fzrq9jv5dy6ayys5ahqslwdm2r3twvkslt6n42",
"pub_key": null,
"account_number": "90",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1fmgs4yazltgd3wazpjsrcgq443e2f3wdpqj4jp",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A5IveUHNjAJEFoFOaNO2wQgWFhIeIV5mvmPZTrMzlIIJ"
},
"account_number": "85",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1fl48vsnmsdzcv85q5d2q4z5ajdha8yu3z7dksy",
"pub_key": null,
"account_number": "9",
"sequence": "0"
},
"name": "bonded_tokens_pool",
"permissions": [
"burner",
"staking"
]
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi12qa3e90tlqlqdvml2kzr78fmxuzdk5d884j04h",
"pub_key": null,
"account_number": "41",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi12205rslyzj8mddde39v6zhkcusmhffw5pdtrrh",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Ao6OmDh3Voof6UU5OwlYhtFoCYz2cc3mqBtMFBF0dEm1"
},
"account_number": "81",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi120kzgarrlar6qx2sc2nrevpzy2jkgq3scsl8k6",
"pub_key": null,
"account_number": "53",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi120ljxpsmmxhljwqss0wgnqsquvs4d5ufwpa2ek",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Asp3X5RR5hYrhFQBiP2wFNSXMW/A++ZnSrtRrJP9QvS9"
},
"account_number": "68",
"sequence": "4855"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi12khskv5x0akf6j6cp3h2e99fmywfx20td8mw0j",
"pub_key": null,
"account_number": "43",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1tq5tfp4pnncmpvj29q4q9ykt9d2ux38uq3hfzg",
"pub_key": null,
"account_number": "98",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1trh2mamq64u4g042zfeevvjk4cukrthvppfnc7",
"pub_key": null,
"account_number": "15",
"sequence": "0"
},
"name": "perp_ef",
"permissions": []
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1tygms3xhhs3yv487phx3dw4a95jn7t7lk738xs",
"pub_key": null,
"account_number": "10",
"sequence": "0"
},
"name": "not_bonded_tokens_pool",
"permissions": [
"burner",
"staking"
]
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1txe948wj7d8rgucfa467xhe6q6k7cdrs7y09e5",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A6HQ2nWU1XKCuxEq3S5Q6bT2M4hllWd1eK+dg35gn3ix"
},
"account_number": "45",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1tt3pq6ry5xuqhd2xrg6n8a7ak72ekd7jcjkct7",
"pub_key": null,
"account_number": "59",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1v94gc7axjp69g2c9qs98w9heft4phted85l4y9",
"pub_key": null,
"account_number": "108",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1vvrcqfpychju3gx5nmk5nqtqxw64edcxk6t5vl",
"pub_key": null,
"account_number": "83",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1vsdfdqzcc0nupdvqsl6j5wht07luwg0gdz08gx",
"pub_key": null,
"account_number": "49",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1v3k6rnzkfp9mak3hnmuuad64wuupmkxlngk9k3",
"pub_key": null,
"account_number": "102",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1dzkrhr0nlj8g7xrjgfv3c3hckxjk4j2gpvaacu",
"pub_key": null,
"account_number": "38",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1d4hsppp3vn6s6wg98a0yj6umld3j7zdsey6qnl",
"pub_key": null,
"account_number": "22",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1wpqm2505hw628p27hcnz4mwxkfv609k2z67x4k",
"pub_key": null,
"account_number": "96",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1wfse6ncrzksrwaekdwnw464q574p6seak037p5",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Aj0DTk5WFUi/VQFOvDov0Z4VIP448+tqpjolyUPId6Pj"
},
"account_number": "48",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1w5rh8edees3y5pslg004spfmcztlrcr3h8w5t9",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Andw/IuP1tAfy7X0yeCl04XH/9tCkYGUY0tLD7Nz8o1K"
},
"account_number": "57",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1wkgkhn5dhn3jul0u9z0xsxem7j6fxk8fgdzafw",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Awih3PYSBqu8TQT3PvRtMk06wuYzn4/p3x6O/4mccmvW"
},
"account_number": "24",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1wlfmzz3sl0zfpyjsdram6573fptw47q4far3fu",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AlT8S+scrxPtqPCsargdatEG8rTKogGEi7M5Gszudrki"
},
"account_number": "30",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi10t80hx42azdty5cuskhgyay6gals0mn37hk2dm",
"pub_key": null,
"account_number": "87",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi10d07y265gmmuvt4z0w9aw880jnsr700jd8hulq",
"pub_key": null,
"account_number": "11",
"sequence": "0"
},
"name": "gov",
"permissions": [
"burner"
]
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1033uykp2u0whm4zcrxz7f73cqwmux4vqxvjssz",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AmezVVLKrSs8txxkdKWAusbAmuObJ6FBkFOtQHhKl4qQ"
},
"account_number": "66",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1062lp93xpfl8twcsuctm9hjju6qs45dunzha6g",
"pub_key": null,
"account_number": "34",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi10uhw6xg4rrlveh8gd7wyknqg7sp5fv5sjukky4",
"pub_key": null,
"account_number": "101",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1sjexpwrh8wrjspykl5p0976mzlepf7dey6w3dk",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A56lwl4tMvmMT//FXFHiP/lnC3v69dI/yKTcoLHNiCGD"
},
"account_number": "27",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1s5vd0faul09j4fec7d8743hzrjp0hxr26lva5s",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AnCOjP91dxZ9/+bxBR4LsrbnIjHzZfQhezmTyxvyHQsf"
},
"account_number": "63",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1s64pdpjj438r6a5nusxdmm6mpgxge44cpwm0e3",
"pub_key": null,
"account_number": "47",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1s7jt9za5s8yfudvtv0207p9qddqaav094uryfl",
"pub_key": null,
"account_number": "25",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi13v2e9dxs2prjtl6y6msz26xudmxqv2rr0nr099",
"pub_key": null,
"account_number": "26",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi136ege9etqhayar0s99u3m4f4fmc025h5g6gv9m",
"pub_key": null,
"account_number": "92",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1jpkpke5cfduue3dgt2s4pk9zen7jvyymsurcrk",
"pub_key": null,
"account_number": "37",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1j9cshqwrdpv6n8j2258l2wz8fgav9k2598c7hc",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A1UnooMYoCdw9R0gUS5SNHNrUr9a59TUwM2ZeMmNEVX0"
},
"account_number": "36",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1jgk56fqecy8tje9vy00hytrwsgsqsa4x4s3g9c",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AwPObgIWwR5rKK9dGdgrgENkdyYmcEOdO3F2d8u5Xhwm"
},
"account_number": "72",
"sequence": "3"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8s6q9qv",
"pub_key": null,
"account_number": "8",
"sequence": "0"
},
"name": "distribution",
"permissions": []
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1nwvq2x6pk0clugqxqr3kqzl79zu3406vtcqyke",
"pub_key": null,
"account_number": "31",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1n0tnt4fhpfcmxw8aepwmycpzp6da5j3lvcqm9z",
"pub_key": null,
"account_number": "65",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1nu85vvp8lln2hk3rxj7p8r59hll83x480nn0tr",
"pub_key": null,
"account_number": "52",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1nu7s8ytl88a2843522ncwy32k3x8gz9vzkewkf",
"pub_key": null,
"account_number": "86",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1nlucw7hah56e9z2vwzx8u90ak4rqwem725vkdm",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Aq/AC2bGglatBeco7o0PObjLO4634ESaGxaqHirEdaw0"
},
"account_number": "71",
"sequence": "4495"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi15k6d8r90rmqfw68rn7mulv86qsxk7zsg3s2pku",
"pub_key": null,
"account_number": "18",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi15cdcxznuwpuk5hw7t678wpyesy78kwy00qcesa",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A+F5BscUw3IXna3JYfwdGZU7rq8enziW92TBf6vudqUD"
},
"account_number": "3",
"sequence": "14140"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14q849dwpf077tkz3r8p6ay47nugh5n7rd2tl39",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Ax8ibQCbX3YgL/KIXdvoSl4jPPEDPaw0Lg3nxc/EwJj5"
},
"account_number": "75",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14z7w7xrsdqptwd78qt40c7qw03ngawglqp694x",
"pub_key": null,
"account_number": "61",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi143kdcynewz7d08fmlu0ugtnn9sv8vljxwp7eug",
"pub_key": null,
"account_number": "13",
"sequence": "0"
},
"name": "fee_pool",
"permissions": []
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14jrza6nahmc6a6t8qugx93hk8epg4ns5fzrdug",
"pub_key": null,
"account_number": "62",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14j9hsmfhgzmwvmuh2yqcyhggx22e43s3fk22ww",
"pub_key": null,
"account_number": "28",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14chtz40svxemn3avzcuqhmj7gvyrk7sjr2kqw2",
"pub_key": null,
"account_number": "80",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi14arjpwrrgkd8d270dxarjswt3huggzmfwag920",
"pub_key": null,
"account_number": "99",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1k8ju5q4ns3vmvezwuq8enwd4lsk9rt7pl2r0cm",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A6ylFeGyCs4+PsgMkXa7rey++4gpRrlhVrNT8I0QMZy1"
},
"account_number": "94",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1k3ry6nleastz4dktngqgljhtjqc8ayw7gnnmdk",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "A/bZdpIUdtqV3la7+mrOa8fV3OUd+/K4Q3kKlgT7lrXg"
},
"account_number": "54",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1k369gkcjvyuw2j33dprrlfazcl9e72m93d3qds",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AxyyncLL45Fiv7a2qXfJ3un0JNCFqU7s7g+ubCd73mly"
},
"account_number": "60",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1hy9u2ymnt54tp4lzc83pz0t4rr3l08ehkswkfc",
"pub_key": null,
"account_number": "79",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1hx20l4hva2z48kumjlsypuz4p0aad8ze7jy3kr",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AuHYKv2aI/44/m1zv5ycjy3J3IKRkzcy5d2izYEvjvQu"
},
"account_number": "51",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1h07xwnnxpu2r3p8488366xl6n24stk489vtujj",
"pub_key": null,
"account_number": "1",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1hkw4mpraxatgu5cn4guzvr87k2wclqn73q2fkn",
"pub_key": null,
"account_number": "23",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1hcscv88cakrzasnq4u2y4j62nxh556xntnua5k",
"pub_key": null,
"account_number": "2",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1hc5eene8ggwa4972rl9mnvg8f7mp0nrzp6j9qa",
"pub_key": null,
"account_number": "95",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1czwx3kdq2g37nu2qw0dlm0axde2p2trprn5evr",
"pub_key": null,
"account_number": "76",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1crtq7rgr5a2gkf3vgznz5upf3njnq939hwrwvc",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Athy3DMQVqsTomtpqTGwetywWbgETAwmMtxKcI+/llNh"
},
"account_number": "70",
"sequence": "4200"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1ckqd6stcncn6l4kzuejnqy2v4dnsuly55kqpj2",
"pub_key": null,
"account_number": "73",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1c6urm4cec06njl3s85n5rzmwz9psta4s0s34uk",
"pub_key": null,
"account_number": "74",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1c7etup0jqjax96hwjh7dk6wfdgx0huez9lz07z",
"pub_key": null,
"account_number": "35",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1e6fanvkly2rytdg3kg5fr3c7grhl3f84gslv53",
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AjKhaZu3R6RbBK10iXVkB7VZ5NhrXvxguqlVU9LFz0kr"
},
"account_number": "103",
"sequence": "4"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi164y9df30y4ymsnea6uc06r6p3ahcnsglfm5kqr",
"pub_key": null,
"account_number": "40",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi16ay0vuz40net592ddcvkxawv6w3l5jh7d05a4f",
"pub_key": null,
"account_number": "44",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1mpzg0tzxtkmf86xz7ndkl9j6909m38s37wdyz0",
"pub_key": null,
"account_number": "104",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.ModuleAccount",
"base_account": {
"address": "nibi1m3h30wlvsf8llruxtpukdvsy0km2kum8l5rpwn",
"pub_key": null,
"account_number": "12",
"sequence": "0"
},
"name": "mint",
"permissions": [
"minter"
]
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "nibi1uz4rqu944l9wkjgr9kyf6lr209lvv40tjngs4j",
"pub_key": null,
"account_number": "58",
"sequence": "0"
}
],
"pagination": {
"next_key": "5KtWergP5Hlrg66xa+shsQaeaNM=",
"total": "0"
}
}
import nibiru
from nibiru import Sdk, Network
import nibiru.common
Sdk.authorize().with_network(Network.testnet()).query.vpool.all_pools()
outputs:
{
"pools": [
{
"base_asset_reserve": 49998152817.02902,
"fluctuation_limit_ratio": 0.1,
"maintenance_margin_ratio": 0.0625,
"max_leverage": 10.0,
"max_oracle_spread_ratio": 0.1,
"pair": {"token0": "ubtc", "token1": "unusd"},
"quote_asset_reserve": 1000036945024304.0,
"trade_limit_ratio": 0.1,
},
{
"base_asset_reserve": 666666000000.0,
"fluctuation_limit_ratio": 0.1,
"maintenance_margin_ratio": 0.0625,
"max_leverage": 10.0,
"max_oracle_spread_ratio": 0.1,
"pair": {"token0": "ueth", "token1": "unusd"},
"quote_asset_reserve": 1000000000000000.0,
"trade_limit_ratio": 0.1,
},
],
"prices": [
{
"block_number": 101237,
"index_price": 2.005334737212e22,
"mark_price": 20001.477828270858,
"pair": "",
"swap_invariant": 50000000000000000000000000,
"twap_mark": 1.99999743785703e22,
},
{
"block_number": 101237,
"index_price": 0.0,
"mark_price": 1500.0015000015,
"pair": "",
"swap_invariant": 666666000000000000000000000,
"twap_mark": 1.500001500016553e21,
},
],
}
Here and there in liquidator and heart-monitor some unexpected py-sdk messages are appearinng:
12:06:41|DEBUG|_handle_txs| Failed parsing events log: failed to execute message; message index: 0: 0unibi is smaller than 100000000unibi: insufficient funds. Expecting value: line 1 column 1 (char 0)
Need to make sdk and app logging consistent and have an ability to turn off DEBUG if it's not intentionally on.
This issue roughly outlines the expected API which could be used by Liquidation bot / Trading bit / Arbitrage bot
sdk.set_config({"keyring-backend": "test", "node": "localhost:26657" ... })
Whatever else could be needed here
Using private key or mnemonic key.
trader = sdk.create_account(mnemonic_key="cream soda ...")
print(trader.address)
# nibi1zx4j3gq5elhlrp3vqden6vnfz4wk2yqx93k7l9
Using private key or mnemonic key.
trader = sdk.authorize(mnemonic_key="cream soda ...")
print(trader.address)
# nibi1zx4j3gq5elhlrp3vqden6vnfz4wk2yqx93k7l9
balance = sdk.check_balance(account="nibi17ejlwwng0qux44z27calklhv5zx0p98l865cq7")
print(balance)
# {"balances":[{"denom": "nusd", "amount": 1234.00}],"pagination":{"next_key":null,"total":"1"}}
trader = sdk.authorize(mnemonic_key="cream soda ...")
position = trader.open_position(pair="ubtc:unusd", quote_amount=1000, leverage=10, limit=0)
print(position)
# position state in JSON format like in event
trader = sdk.authorize(mnemonic_key="cream soda ...")
position = trader.close_position(pair="ubtc:unusd")
print(position)
# position state in JSON format like in event
position = sdk.get_position(trader="nibi1zx4j3gq5elhlrp3vqden6vnfz4wk2yqx93k7l9", pair="ubtc:unusd")
# position details in JSON format like in event
position = sdk.liquidate(trader="nibi1zx4j3gq5elhlrp3vqden6vnfz4wk2yqx93k7l9", pair="ubtc:unusd")
# position details in JSON format Liquidation event
As a baseline, we need to expose functions for:
transfer
involved in cosmos.bank.v1beta1.MsgSend
nibiru.vpool.v1.MarkPriceChanged
Lower priority but nice to have:
nibiru.vpool.v1.ReserveSnapshotSavedEvent
nibiru.vpool.v1.SwapQuoteForBaseEvent
Use ping test like ts-sdk to check RPC and LCD connections befrore running tests
This command is working:
nibid tx perp open-position buy axlwbtc:unusd 1 500000000 1 --from test22 --keyring-backend test --chain-id nibiru-localnet-0 --broadcast-mode block -y --gas 99999999999
But doing this:
trader.tx.perp.open_position(
sender=trader.address,
side=Side.BUY,
quote_asset_amount="500000000",
leverage="5",
base_asset_amount_limit="1",
token_pair="axlwbtc:unusd",
)
leads to not enough base for the amount specified.
The LCD and GRPC endpoints could have different domain names, so relying on HOST
won't work. There needs to be separate LCD_ENDPOINT
and GRPC_ENDPOINT
env variables.
Recommended package: [pytest-cov](Ref: https://pypi.org/project/pytest-cov/)
pytest --cov=myproj tests/
Would produce a report like:
-------------------- coverage: ... ---------------------
Name Stmts Miss Cover
----------------------------------------
myproj/__init__ 2 0 100%
myproj/myproj 257 13 94%
myproj/feature4286 94 7 92%
----------------------------------------
TOTAL 353 20 94%
_InactiveRpcError Traceback (most recent call last)
Input In [6], in <cell line: 1>()
----> 1 trader = nibiru.Sdk.authorize().with_network(network, insecure=True)
File /opt/homebrew/lib/python3.10/site-packages/nibiru/sdk.py:111, in Sdk.with_network(self, network, insecure, bypass_version_check)
98 """
99 Change the network of the sdk to the specified network.
100
(...)
107 Sdk: The updated sdk object
108 """
109 self.network = network
110 self._with_query_client(
--> 111 GrpcClient(self.network, insecure, bypass_version_check)
112 )
113 return self
File /opt/homebrew/lib/python3.10/site-packages/nibiru/client.py:89, in GrpcClient.init(self, network, insecure, credentials, bypass_version_check)
83 import importlib_metadata as metadata
85 nibiru_proto_version = metadata.version("nibiru_proto")
87 self.assert_compatible_versions(
88 nibiru_proto_version=nibiru_proto_version,
---> 89 chain_nibiru_version=str(self.get_version()),
90 )
File /opt/homebrew/lib/python3.10/site-packages/nibiru/client.py:180, in GrpcClient.get_version(self)
178 def get_version(self) -> tendermint_query.GetLatestBlockResponse:
179 req = tendermint_query.GetNodeInfoRequest()
--> 180 version = self.stubCosmosTendermint.GetNodeInfo(req).application_version.version
182 if version[0] != "v":
183 version = "v" + str(version)
File /opt/homebrew/lib/python3.10/site-packages/grpc/_channel.py:946, in _UnaryUnaryMultiCallable.call(self, request, timeout, metadata, credentials, wait_for_ready, compression)
937 def call(self,
938 request,
939 timeout=None,
(...)
942 wait_for_ready=None,
943 compression=None):
944 state, call, = self._blocking(request, timeout, metadata, credentials,
945 wait_for_ready, compression)
--> 946 return _end_unary_response_blocking(state, call, False, None)
File /opt/homebrew/lib/python3.10/site-packages/grpc/_channel.py:849, in _end_unary_response_blocking(state, call, with_call, deadline)
847 return state.response
848 else:
--> 849 raise _InactiveRpcError(state)
_InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:9090: Failed to connect to remote host: Connection refused"
debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:9090: Failed to connect to remote host: Connection refused {grpc_status:14, created_time:"2022-12-05T19:00:55.652046-05:00"}"
0.0.18
- >WrongHere is a result of SDK query.vpool.all_pools()
:
All values are strings, not deserialized.
{
"pools": [
{
"pair": {
"token0": "ubtc",
"token1": "unusd"
},
"base_asset_reserve": "1000000000000000000000",
"quote_asset_reserve": "23400000000000000000000000",
"trade_limit_ratio": "100000000000000000",
"fluctuation_limit_ratio": "100000000000000000",
"max_oracle_spread_ratio": "100000000000000000",
"maintenance_margin_ratio": "62500000000000000",
"max_leverage": "12000000000000000000"
},
{
"pair": {
"token0": "ueth",
"token1": "unusd"
},
"base_asset_reserve": "666666000000000000000000000000",
"quote_asset_reserve": "1000000000000000000000000000000000",
"trade_limit_ratio": "100000000000000000",
"fluctuation_limit_ratio": "100000000000000000",
"max_oracle_spread_ratio": "100000000000000000",
"maintenance_margin_ratio": "62500000000000000",
"max_leverage": "10000000000000000000"
}
],
"prices": [
{
"mark_price": "23400000000000000000000",
"index_price": "0",
"twap_mark": "23400000000000000000000",
"swap_invariant": "23400000000",
"block_number": "126"
},
{
"mark_price": "1500001500001500001500",
"index_price": "0",
"twap_mark": "1500001500001500001500",
"swap_invariant": "666666000000000000000000000",
"block_number": "126"
}
]
}
0.0.17
-> Right{
"pools": [
{
"base_asset_reserve": 1000.0,
"fluctuation_limit_ratio": 0.1,
"maintenance_margin_ratio": 0.0625,
"max_leverage": 12.0,
"max_oracle_spread_ratio": 0.1,
"pair": {
"token0": "ubtc",
"token1": "unusd"
},
"quote_asset_reserve": 23400000.0,
"trade_limit_ratio": 0.1
},
{
"base_asset_reserve": 666666000000.0,
"fluctuation_limit_ratio": 0.1,
"maintenance_margin_ratio": 0.0625,
"max_leverage": 10.0,
"max_oracle_spread_ratio": 0.1,
"pair": {
"token0": "ueth",
"token1": "unusd"
},
"quote_asset_reserve": 1000000000000000.0,
"trade_limit_ratio": 0.1
}
],
"prices": [
{
"block_number": 216,
"index_price": 0.0,
"mark_price": 23400.0,
"swap_invariant": "23400000000",
"twap_mark": 23400.0
},
{
"block_number": 216,
"index_price": 0.0,
"mark_price": 1500.0015000015,
"swap_invariant": "666666000000000000000000000",
"twap_mark": 1500.0015000015
}
]
}
https://pypi.org/project/nibiru/
Homepage link is wrong: https://github.com/NibiruChain/sdk-py
Regression is coming from this commit: 67745c9#diff-1a2df94eabb4ad224bb6f46a1f2af79b1b236e61f506b118ea8eaa8844084384R112
except grpc.RpcError as err:
return json.loads(err._state.debug_error_string)["grpc_message"], False
Try opening position with insufficient funds:
err._state.debug_error_string =
'UNKNOWN:Error received from peer ipv6:%5B::1%5D:9090 {grpc_message:"failed to execute message; message index: 0: 0unusd is smaller than 10unusd: insufficient funds", grpc_status:2, created_time:"2022-08-15T17:56:51.182382+04:00"}'
This is not json and instead of a regular message I'm getting another exception:
JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
@matthiasmatt @Unique-Divine - please take a look. If GRPC errors are expected to be JSON formatted - please fix the chain, otherwise remove parsing json.
New query from v0.15.0 needs to be added
Make devnet and/or testnet the default with optional environment variables to use localnet. We can use the Network.devnet
and Network.localnet
fns to accomplish this.
Has anybody even tried this? ) I encountered with this while trying to liquidate multiple positions but it looks even simple send fails
tx_output = validator.tx.execute_msgs(
[
MsgSend(
validator.address, trader.address,
[
Coin(1000_000, "unibi"),
Coin(100, "unusd")
]
),
MsgSend(
validator.address, trader.address,
[
Coin(1000_000, "unibi"),
Coin(200, "unusd")
]
)
]
)
Traceback (most recent call last):
File "/Users/onikonychev/Library/Caches/pypoetry/virtualenvs/liquidation-QJ54D7zn-py3.10/lib/python3.10/site-packages/nibiru/tx.py", line 72, in execute_msgs
.with_messages(pb_msgs)
File "/Users/onikonychev/Library/Caches/pypoetry/virtualenvs/liquidation-QJ54D7zn-py3.10/lib/python3.10/site-packages/nibiru/transaction.py", line 47, in with_messages
self.msgs.extend(self.__convert_msgs(msgs))
File "/Users/onikonychev/Library/Caches/pypoetry/virtualenvs/liquidation-QJ54D7zn-py3.10/lib/python3.10/site-packages/nibiru/transaction.py", line 42, in __convert_msgs
any_msg.Pack(*msg, type_url_prefix="")
TypeError: Any.Pack() got multiple values for argument 'type_url_prefix'
poetry install
poetry run pytest
Using any bump rule with a valid semver string will change the version inside pyproject.toml
. For example,
poetry version patch # moves from x.y.14 to x.y.15
poetry version minor # moves from x.5.z to x.6.0
poetry version major # moves from 3.y.z to 4.0.0
The list of bump rules includes:
patch, minor, major, prepatch, preminor, premajor, prerelease.
# Rough outline to get someone started
job_name:
runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, 'SKIP BUMP')" <--- skips everything in this job if head commit message does not contain 'SKIP BUMP'
steps:
- uses: ....
- name: condition 1
if: "contains(github.event.head_commit.message, 'CONDITION 1 MSG')"
run: command(s) for condition 1
- name: not condition 2
if: "!contains(github.event.head_commit.message, 'CONDITION 2 MSG')"
run: command(s) for condition 2
# ...
poetry build
poetry publish --username $PYPI_USER --password $PYPI_TOKEN
Bank balance query output is coming back unserialized:
> agent.query.get_bank_balances(agent.address)
balances {
denom: "unibi"
amount: "10000000"
}
balances {
denom: "unusd"
amount: "100000000000"
}
pagination {
total: 2
}
This is likely due to an issue in the deserialize function
This endblocker event EventPairPriceUpdated
is not caught although it is part of the websocket dump. Most likely not the right route of json is being parsed.
When executing this:
trader = nib.Sdk.authorize(MNEMONIC)
trader.tx.dex.create_pool(
creator=trader.address,
swap_fee=0.02,
exit_fee=0.1,
assets=[
nib.PoolAsset(
token=nib.Coin(
denom="unibi",
amount=1000,
),
weight=50
),
nib.PoolAsset(
token=nib.Coin(
denom="unusd",
amount=10000,
),
weight=50
),
]
)
I get this:
{
"address": "nibi1vm70ju9n2laspspsh6fs2hu50z3qzf4m2emr0p",
"id": 2,
"pool_assets": [
{
"token": {
"amount": "1000",
"denom": "unibi"
},
"weight": "53687091200"
},
{
"token": {
"amount": "10000",
"denom": "unusd"
},
"weight": "53687091200"
}
],
"pool_params": {
"exit_fee": 0.002251799813685248,
"swap_fee": 0.000562949953421312
},
"total_shares": {
"amount": "100000000000000000000",
"denom": "nibiru/pool/2"
},
"total_weight": "107374182400"
}
]
}
The fee seems to be not parsed correctly. When looking at the CLI query, i also see this pool with weird fees:
❯ nibid q dex get-pool 2
pool:
address: nibi1vm70ju9n2laspspsh6fs2hu50z3qzf4m2emr0p
id: "2"
pool_assets:
- token:
amount: "1000"
denom: unibi
weight: "53687091200"
- token:
amount: "10000"
denom: unusd
weight: "53687091200"
pool_params:
exit_fee: "0.002251799813685248"
swap_fee: "0.000562949953421312"
total_shares:
amount: "100000000000000000000"
denom: nibiru/pool/2
total_weight: "107374182400"
For nibiru-proto
v0.14, the response for the all-pools
query has some number fields as regular strings because it allows missing values to appear as empty strings.
The fields that need conversions are the index price and mark TWAP.
Live logging is possible with pytest
and super useful. This stackoverflow answer has decent instructions on how to set it up.
Logging is part of the standard library. You can create one with logging.getLogger
. Since we already use a pyproject.toml
, it will be quick to set up log_cli
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.