diff --git a/.gitignore b/.gitignore index 4ea2de70..891aca65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ __pycache__ +.venv +venv +credentials.* +credentials *.tmp +.idea +.DS_Store +token.temp tools/ diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 00000000..8ee4c2eb --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,5 @@ +FROM gitpod/workspace-full:latest + +# Install gq +ENV PATH="$PATH:$HOME/node_modules/.bin" +RUN npm install graphqurl@0.3.3 \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000..3ad8ff10 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,12 @@ +--- + +image: + file: .gitpod.Dockerfile + +tasks: + - init: pipenv install -r requirements.txt --python 3.8 + - command: | + pipenv shell + source examples-config + +ports: [] diff --git a/README.md b/README.md index af867e21..9f63f4b3 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,9 @@ The per-language API clients are found in [`grpc/clients/`](https://github.com/v Pull requests for additional languages are gratefully received. -# Examples +# Example API scripts + +[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/vegaprotocol/api/tree/198-api-examples/) Some example/demonstration programs are maintained in this repository. They are intended to be stand-alone programs that can be run by people copying and diff --git a/examples-config b/examples-config new file mode 100644 index 00000000..01697d01 --- /dev/null +++ b/examples-config @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Default server configuration used by REST/GRPC/GRAPHQL examples + +NODE_URL_REST="https://lb.testnet.vega.xyz" +NODE_URL_GRAPHQL="https://lb.testnet.vega.xyz/query" +NODE_URL_GRPC="n06.testnet.vega.xyz:3002" +WALLETSERVER_URL="https://wallet.testnet.vega.xyz" + +export NODE_URL_GRPC +export NODE_URL_REST +export NODE_URL_GRAPHQL +export WALLETSERVER_URL diff --git a/examples-config.ps1 b/examples-config.ps1 new file mode 100644 index 00000000..5dfd4c06 --- /dev/null +++ b/examples-config.ps1 @@ -0,0 +1,9 @@ +# Set env variable on a Window computer +$Env:WALLET_NAME="example_wallet_name" +$Env:WALLET_PASSPHRASE="example_wallet_passphrase" + +# Do not edit below this line: +$Env:WALLETSERVER_URL="https://wallet.testnet.vega.xyz" +$Env:NODE_URL_REST="https://lb.testnet.vega.xyz" +$Env:NODE_URL_GRAPHQL="https://lb.testnet.vega.xyz/query" +$Env:NODE_URL_GRPC="n06.testnet.vega.xyz:3002" diff --git a/go.mod b/go.mod index 8b2f9536..883163ec 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,15 @@ module github.com/vegaprotocol/api go 1.16 require ( + code.vegaprotocol.io/go-wallet v0.8.0 github.com/golang/protobuf v1.5.2 github.com/mwitkow/go-proto-validators v0.3.2 + github.com/pkg/errors v0.9.1 github.com/satori/go.uuid v1.2.0 github.com/stretchr/testify v1.7.0 - google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 - google.golang.org/grpc v1.38.0 + golang.org/x/net v0.0.0-20210610132358-84b48f89b13b + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b + google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea + google.golang.org/grpc v1.39.0 google.golang.org/protobuf v1.27.1 ) diff --git a/go.sum b/go.sum index 3cfd900c..387ba598 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,66 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +code.vegaprotocol.io/go-wallet v0.8.0 h1:NoNWtybERs2hvgBfiNLTxPgZoCbKhmVuqMCkLD5ncRc= +code.vegaprotocol.io/go-wallet v0.8.0/go.mod h1:I6BGRx6wGt+VMuHGW/IKabKEC1HydXSdKuden61qMAQ= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs= +github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -23,9 +68,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -33,133 +80,208 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos= github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w= +github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b h1:MKwruh+HeCSKWphkxuzvRzU4QzDkg7yiPkDVV0cDFgI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b/go.mod h1:TLJifjWF6eotcfzDjKZsDqWJ+73Uvj/N85MvVyrvynM= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/vegaprotocol/api v0.38.0/go.mod h1:5Zl3has/kHmU06i1BDGczwhcKVED5R+SqVchfZstiwY= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zannen/toml v0.3.2 h1:IYPp4GVtabUyQpzSU6xP1VDyKR3Ico3qhNP2VxCkl2Y= +github.com/zannen/toml v0.3.2/go.mod h1:17qwsU2a1aZpHAu+nMR+zAzGupaxRIaCvxBhvCp5YGk= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 h1:z+j74wi4yV+P7EtK9gPLGukOk7mFOy9wMQaC0wNb7eY= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a h1:VA0wtJaR+W1I11P2f535J7D/YxyvEFMTMvcmyeZ9FBE= -google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210518161634-ec7691c0a37d h1:bRz6UmsZEz/CzoTjUDp4ZcdguhSWi6CyU299wMQBpZU= -google.golang.org/genproto v0.0.0-20210518161634-ec7691c0a37d/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210521181308-5ccab8a35a9a h1:FaCiYXNZoBH/gnmVjMAHgOgdmpVVROBYOA+qCOHh6Hc= -google.golang.org/genproto v0.0.0-20210521181308-5ccab8a35a9a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210524142926-3e3a6030be83 h1:1RnejfrmpVDN9Cq4r1SXBxk74lYLP/w6wOu6NbETf0Y= -google.golang.org/genproto v0.0.0-20210524142926-3e3a6030be83/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210524171403-669157292da3 h1:xFyh6GBb+NO1L0xqb978I3sBPQpk6FrKO0jJGRvdj/0= -google.golang.org/genproto v0.0.0-20210524171403-669157292da3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210603172842-58e84a565dcf h1:3oVOonZQld/0ddUsMXCnkhem95RnnQEUMZQLJP1s3jQ= -google.golang.org/genproto v0.0.0-20210603172842-58e84a565dcf/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08 h1:pc16UedxnxXXtGxHCSUhafAoVHQZ0yXl8ZelMH4EETc= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210607140030-00d4fb20b1ae h1:2dB4bZ/B7RJdKuvHk3mKTzL2xwrikb+Y/QQy7WdyBPk= -google.golang.org/genproto v0.0.0-20210607140030-00d4fb20b1ae/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d h1:KzwjikDymrEmYYbdyfievTwjEeGlu+OM6oiKBkF3Jfg= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210610141715-e7a9b787a5a4 h1:Kgs5nmbQVuUAug2PXQ27hu9MSCv8uJTnrmxZj9Lj5lc= -google.golang.org/genproto v0.0.0-20210610141715-e7a9b787a5a4/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210611144927-798beca9d670 h1:M9c2dapWGIISuWaz5vr/RUk5Qn2Hs8DZ9CJb5aH266Q= google.golang.org/genproto v0.0.0-20210611144927-798beca9d670/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus= -google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 h1:R1r5J0u6Cx+RNl/6mezTw6oA14cmKC96FeUwL6A9bd4= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea h1:8ZyCcgugUqamxp/vZSEJw9CMy7VZlSWYJLLJPi/dSDA= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -170,16 +292,25 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.0 h1:KhgSLlr/moiqjv0qUsSnLvdUL7NH7PHW8aZGn7Jpjko= -google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/graphql/examples/event-bus/stream-events.sh b/graphql/examples/event-bus/stream-events.sh new file mode 100755 index 00000000..232cd044 --- /dev/null +++ b/graphql/examples/event-bus/stream-events.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +# Script language: bash + +# Talks to: +# - Vega node (GraphQL) +# +# Apps/Libraries: +# - GraphQL: graphqurl (https://github.com/hasura/graphqurl) + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +source helpers.sh +check_url "NODE_URL_REST" || exit 1 +check_url "NODE_URL_GRAPHQL" || exit 1 + +# __get_market: +# Request the identifier for a market +url="$NODE_URL_REST/markets" +response="$(curl -s "$url")" +marketID="$(echo "$response" | jq -r '.markets[0].id')" +echo $marketID +# :get_market__ + +# __stream_events: +# Subscribe to the events bus stream for the marketID specified, +# Required: type field - Switch the event type with '... on [TYPE]' syntax, NOTE: All event is not supported by GraphQL API. +# Required: batchSize field - Default: 0 - Total number of events to batch on server before sending to client. +# Optional: Market identifier - filter by market +# Party identifier - filter by party +# By default, all events on all markets for all parties will be returned on the stream. +# Event types and schema can be found here: https://docs.testnet.vega.xyz/docs/api-howtos/event-stream/ +gq $NODE_URL_GRAPHQL -q 'subscription { busEvents(batchSize: 0, types: [Order], marketID: "'$marketID'" ) { + type + event + { + ... on Order { + id + side + price + timeInForce + side + market { id } + size + remaining + party { id } + createdAt + expiresAt + status + reference + trades { id, size, aggressor } + type + rejectionReason + version + updatedAt + } + ... on TimeUpdate { + timestamp + } + } +}}' +# :stream_events__ + +# Another example, with even deeper graphql nesting would be to select on Governance Proposals: +# +# gq $NODE_URL_GRAPHQL -q 'subscription { busEvents(batchSize: 0, types: [Proposal] ) { +# type +# event +# { +# ... on Proposal { +# id +# datetime +# yesVotes { +# value +# party { id } +# } +# noVotes { +# value +# party { id } +# } +# party { +# id +# } +# reference +# state +# terms { +# closingDatetime +# enactmentDatetime +# change { +# ... on NewMarket { +# instrument { +# code +# } +# decimalPlaces +# tradingMode { +# ... on ContinuousTrading { +# tickSize +# } +# ... on DiscreteTrading { +# tickSize +# duration +# } +# } +# riskParameters { +# ... on LogNormalRiskModel { +# tau +# riskAversionParameter +# params { +# r +# sigma +# mu +# } +# } +# } +# } +# ... on NewAsset { +# source { +# ... on BuiltinAsset { +# id +# } +# } +# } +# } +# } +# } +# } +# } +# }' diff --git a/graphql/examples/orders-and-trades/stream-orders.sh b/graphql/examples/orders-and-trades/stream-orders.sh new file mode 100755 index 00000000..bf95f99e --- /dev/null +++ b/graphql/examples/orders-and-trades/stream-orders.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Script language: bash + +# Talks to: +# - Vega node (GraphQL) +# +# Apps/Libraries: +# - GraphQL: graphqurl (https://github.com/hasura/graphqurl) + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +source helpers.sh +check_url "NODE_URL_GRAPHQL" || exit 1 + +# __stream_orders_by_ref: +# Stream orders by reference on a Vega network +# Note: This is an example and order reference will be provided in the response +# from a prepareSubmitOrder request in the field named `submitID` or similar. +reference="4617844f-6fab-4cf6-8852-e29dbd96e5f1" +pubkey="94c21a5bfc212c0b4ee6e3593e8481559972ad31f1fb453491f255e72bdb6fdb" +gq $NODE_URL_GRAPHQL -q 'subscription { orders(partyId: "'$pubkey'") { id, reference } }' +# In target language, filter the result stream and search for orders matching the reference +# :stream_orders_by_ref__ diff --git a/grpc/examples/go/get-accounts.go b/grpc/examples/go/get-accounts.go new file mode 100644 index 00000000..0b506070 --- /dev/null +++ b/grpc/examples/go/get-accounts.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Get market + marketRequest := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &marketRequest) + if err != nil { + panic(err) + } + marketID := markets.Markets[0].Id + + // __get_accounts_by_market: + // Request a list of accounts for a market on a Vega network + accountsReq := api.MarketAccountsRequest{MarketId: marketID} + acconutsResp, err := dataClient.MarketAccounts(context.Background(), &accountsReq) + if err != nil { + panic(err) + } + fmt.Printf("Market accounts: %v\n", acconutsResp) + // :get_accounts_by_market__ + + // __get_accounts_by_party: + // Request a list of accounts for a party (pubkey) on a Vega network + partyReq := api.PartyAccountsRequest{PartyId: pubkey} + partyResp, err := dataClient.PartyAccounts(context.Background(), &partyReq) + if err != nil { + panic(err) + } + fmt.Printf("Party accounts: %v\n", partyResp) + // :get_accounts_by_party__ + + // __get_positions_by_party: + // Request a list of positions for a party (pubkey) on a Vega network + partyPosReq := api.PositionsByPartyRequest{PartyId: pubkey} + partyPosResp, err := dataClient.PositionsByParty(context.Background(), &partyPosReq) + if err != nil { + panic(err) + } + fmt.Printf("Party positions: %v\n", partyPosResp) + // :get_positions_by_party__ +} diff --git a/grpc/examples/go/get-assets.go b/grpc/examples/go/get-assets.go new file mode 100644 index 00000000..792e1305 --- /dev/null +++ b/grpc/examples/go/get-assets.go @@ -0,0 +1,60 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_assets: + // Request a list of assets available on a Vega network + request := api.AssetsRequest{} + assets, err := dataClient.Assets(context.Background(), &request) + if err != nil { + panic(err) + } + // :get_assets__ + + // Find asset with name DAI + assetFound := false + var assetId string + for _, asset := range assets.Assets { + fmt.Printf("Assets: %s \n", asset.Details.Name) + fmt.Printf("Assets: %s \n", asset.Details.Symbol) + if asset.Details.Symbol == "tDAI" { + fmt.Println("Found an asset with name tDAI:") + assetId = asset.Id + assetFound = true + break + } + } + + if !assetFound { + panic("tDAI asset not found on specified Vega network, please propose and create the tDAI asset") + } + + // __get_asset: + // Request a single asset by identifier on a Vega network + requestAsset := api.AssetByIDRequest{Id: assetId} + assetObject, err := dataClient.AssetByID(context.Background(), &requestAsset) + if err != nil { + panic(err) + } + // :get_asset__ + + fmt.Printf("Asset by id: %s", assetObject.Asset) +} diff --git a/grpc/examples/go/get-fees-margins-estimate.go b/grpc/examples/go/get-fees-margins-estimate.go new file mode 100644 index 00000000..99d1e4ed --- /dev/null +++ b/grpc/examples/go/get-fees-margins-estimate.go @@ -0,0 +1,81 @@ +package main + +import ( + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Find market + // __get_market: + // Request a list of markets available on the specified Vega Network + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + // :get_market__ + + marketID := markets.Markets[0].Id + fmt.Printf("Market id: %s\n", marketID) + + // Fee estimation + // __get_fees_estimate: + // Request to estimate trading fees on a Vega network + order := proto.Order{ + MarketId: marketID, + PartyId: pubkey, + Price: 100000, + Size: 100, + Side: proto.Side_SIDE_BUY, + TimeInForce: proto.Order_TIME_IN_FORCE_GTC, + Type: proto.Order_TYPE_LIMIT, + } + estimationRequest := api.EstimateFeeRequest{Order: &order} + estimation, err := dataClient.EstimateFee(context.Background(), &estimationRequest) + if err != nil { + panic(err) + } + fmt.Printf("Estimation: %v\n", estimation) + // :get_fees_estimate__ + + // Margin estimation + // __get_margins_estimate: + // Request to estimate trading margin on a Vega network + order = proto.Order{ + MarketId: marketID, + PartyId: pubkey, + Price: 600000, + Size: 100, + Side: proto.Side_SIDE_BUY, + TimeInForce: proto.Order_TIME_IN_FORCE_GTC, + Type: proto.Order_TYPE_LIMIT, + } + marginRequest := api.EstimateMarginRequest{Order: &order} + margin, err := dataClient.EstimateMargin(context.Background(), &marginRequest) + if err != nil { + panic(err) + } + fmt.Printf("Margin estimation: %v\n", margin) + // :get_margins_estimate__ +} diff --git a/grpc/examples/go/get-markets-and-marketdata.go b/grpc/examples/go/get-markets-and-marketdata.go new file mode 100644 index 00000000..ca20a483 --- /dev/null +++ b/grpc/examples/go/get-markets-and-marketdata.go @@ -0,0 +1,45 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_markets: + // Request a list of markets available on the specified Vega Network + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("Markets: %s", markets) + // :get_markets__ + marketId := markets.Markets[0].Id + + // __get_market_data: + // Request a single market by identifier on a Vega network + requestMarket := api.MarketByIDRequest{MarketId: marketId} + MarketObject, err := dataClient.MarketByID(context.Background(), &requestMarket) + if err != nil { + panic(err) + } + + fmt.Printf("MarketData: %s", MarketObject) + // :get_market_data__ +} diff --git a/grpc/examples/go/get-network-parameters.go b/grpc/examples/go/get-network-parameters.go new file mode 100644 index 00000000..690c0964 --- /dev/null +++ b/grpc/examples/go/get-network-parameters.go @@ -0,0 +1,33 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_network_params: + // Request a list of network parameters configured on a Vega network + request := api.NetworkParametersRequest{} + network, err := dataClient.NetworkParameters(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("Network Parameters: %s", network) + // :get_network_params__ +} diff --git a/grpc/examples/go/get-order-by-reference.go b/grpc/examples/go/get-order-by-reference.go new file mode 100644 index 00000000..f425f1c4 --- /dev/null +++ b/grpc/examples/go/get-order-by-reference.go @@ -0,0 +1,36 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_order_by_ref: + // Request an order by reference on a Vega network + // Note: This is an example and order reference will be provided in the response + // from a prepareSubmitOrder request in the field named `submitID` or similar. + reference := "4617844f-6fab-4cf6-8852-e29dbd96e5f1" + request := api.OrderByReferenceRequest{Reference: reference} + order, err := dataClient.OrderByReference(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("OrderByReference: %s", order) + // :get_order_by_ref__ +} diff --git a/grpc/examples/go/get-orders-and-trades-for-market.go b/grpc/examples/go/get-orders-and-trades-for-market.go new file mode 100644 index 00000000..e13d7da4 --- /dev/null +++ b/grpc/examples/go/get-orders-and-trades-for-market.go @@ -0,0 +1,53 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Request a list of markets available on the specified Vega Network + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("Markets: %s", markets) + marketID := markets.Markets[0].Id + + // __get_orders_for_market: + // Request a list of orders by market on a Vega network + ordersByMarketReq := api.OrdersByMarketRequest{MarketId: marketID} + ordersByMarketResp, err := dataClient.OrdersByMarket(context.Background(), &ordersByMarketReq) + if err != nil { + panic(err) + } + fmt.Printf("OrdersByMarket: %v\n", ordersByMarketResp) + // :get_orders_for_market__ + + // __get_trades_for_market: + //Request a list of trades by market on a Vega network + tradesByMarketReq := api.TradesByMarketRequest{MarketId: marketID} + tradesByMarketResp, err := dataClient.TradesByMarket(context.Background(), &tradesByMarketReq) + if err != nil { + panic(err) + } + fmt.Printf("TradesByMarket: %v\n", tradesByMarketResp) + // :get_trades_for_market__ + +} diff --git a/grpc/examples/go/get-orders-and-trades-for-party.go b/grpc/examples/go/get-orders-and-trades-for-party.go new file mode 100644 index 00000000..72d1d16f --- /dev/null +++ b/grpc/examples/go/get-orders-and-trades-for-party.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_orders_for_party: + // Request a list of orders by party (pubKey) + ordersByPartyReq := api.OrdersByPartyRequest{PartyId: pubkey} + ordersByPartyResp, err := dataClient.OrdersByParty(context.Background(), &ordersByPartyReq) + if err != nil { + panic(err) + } + fmt.Printf("OrdersByParty: %v\n", ordersByPartyResp) + // :get_orders_for_party__ + + // __get_trades_for_party: + //Request a list of trades by market on a Vega network + tradesByPartyReq := api.TradesByPartyRequest{PartyId: pubkey} + tradesByPartyResp, err := dataClient.TradesByParty(context.Background(), &tradesByPartyReq) + if err != nil { + panic(err) + } + fmt.Printf("TradesByParty: %v\n", tradesByPartyResp) + // :get_trades_for_party__ +} diff --git a/grpc/examples/go/get-parties.go b/grpc/examples/go/get-parties.go new file mode 100644 index 00000000..f8cc8b91 --- /dev/null +++ b/grpc/examples/go/get-parties.go @@ -0,0 +1,45 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_parties: + // Request a list of parties trading on a Vega network + request := api.PartiesRequest{} + parties, err := dataClient.Parties(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("Parties: %v\n", parties) + // :get_parties__ + + partyID := parties.Parties[0].Id + // __get_party_by_id: + // Request a party by their identifier (this is their public key) + partyByIDReq := api.PartyByIDRequest{PartyId: partyID} + partyByIDResp, err := dataClient.PartyByID(context.Background(), &partyByIDReq) + if err != nil { + panic(err) + } + + fmt.Printf("PartyById: %v\n", partyByIDResp.Party) + // :get_party_by_id__ +} diff --git a/grpc/examples/go/get-proposals.go b/grpc/examples/go/get-proposals.go new file mode 100644 index 00000000..4af3d576 --- /dev/null +++ b/grpc/examples/go/get-proposals.go @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // List proposals + // __get_proposals: + // Request a list of proposals on a Vega network + + proposalsRequest := api.GetProposalsRequest{} + proposalsRequest = api.GetProposalsRequest{} + proposalResponse, err := dataClient.GetProposals(context.Background(), &proposalsRequest) + fmt.Printf("Proposals: %+v\n", proposalResponse) + // :get_proposals__ + + if len(proposalResponse.Data) == 0 { + fmt.Println("No open proposal, exit!") + return + } + + proposalID := proposalResponse.Data[0].Proposal.Id + + // Get proposal details + // __get_proposal_detail: + // Request results of a specific proposal on a Vega network + proposalByIDRequest := api.GetProposalByIDRequest{ProposalId: proposalID} + proposalByIDResponse, err := dataClient.GetProposalByID(context.Background(), &proposalByIDRequest) + + fmt.Printf("ProposalById: %+v\n", proposalByIDResponse) + // :get_proposal_detail__ + + // Party proposals + // __get_proposals_by_party: + // Request results of a specific proposal on a Vega network + proposalsByPartyIDRequest := api.GetProposalsByPartyRequest{PartyId: pubkey} + proposalsByPartyIDResponse, err := dataClient.GetProposalsByParty(context.Background(), &proposalsByPartyIDRequest) + + fmt.Printf("ProposalByPartyId: %+v\n", proposalsByPartyIDResponse) + // :get_proposals_by_party__ + +} diff --git a/grpc/examples/go/get-statistics.go b/grpc/examples/go/get-statistics.go new file mode 100644 index 00000000..d712d921 --- /dev/null +++ b/grpc/examples/go/get-statistics.go @@ -0,0 +1,33 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_statistics: + // Request the statistics for a node on Vega + request := api.StatisticsRequest{} + statistics, err := dataClient.Statistics(context.Background(), &request) + if err != nil { + panic(err) + } + + fmt.Printf("Network statistics: %s", statistics) + // :get_statistics__ +} diff --git a/grpc/examples/go/get-time.go b/grpc/examples/go/get-time.go new file mode 100644 index 00000000..8032ae81 --- /dev/null +++ b/grpc/examples/go/get-time.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_time: + // Request the latest timestamp in nanoseconds since epoch from the Vega network + request := api.GetVegaTimeRequest{} + vegaTime, err := dataClient.GetVegaTime(context.Background(), &request) + + // The "timestamp" field contains the resulting data we need. + fmt.Printf("Vega time: %s", vegaTime.Timestamp) + // :get_time__ +} diff --git a/grpc/examples/go/get-trades-for-order.go b/grpc/examples/go/get-trades-for-order.go new file mode 100644 index 00000000..7dcb0fa1 --- /dev/null +++ b/grpc/examples/go/get-trades-for-order.go @@ -0,0 +1,34 @@ +package main + +import ( + "context" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_trades_for_order: + // Request a list of trades for a specific order on a Vega network + orderID := "V0000929211-0046318720" + tradesByOrderReq := api.TradesByOrderRequest{OrderId: orderID} + tradesByOrderResp, err := dataClient.TradesByOrder(context.Background(), &tradesByOrderReq) + if err != nil { + panic(err) + } + fmt.Printf("TradesByOrder: %v\n", tradesByOrderResp) + // :get_trades_for_order__ + +} diff --git a/grpc/examples/go/helpers/wallet.go b/grpc/examples/go/helpers/wallet.go new file mode 100644 index 00000000..96411c02 --- /dev/null +++ b/grpc/examples/go/helpers/wallet.go @@ -0,0 +1,261 @@ +package helpers + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + "syscall" + + "code.vegaprotocol.io/go-wallet/service" + + "golang.org/x/term" +) + +var token string +var pubkey string +var headers string +var tokenFile = "token.temp" +var ciArgs = "--ci" + +func GetFromEnv(envVar string) string { + ev := os.Getenv(envVar) + if len(ev) == 0 { + panic(fmt.Sprintf("%s is null or empty", envVar)) + } + return ev +} + +func existsInArgs(argVal string) bool { + for i, a := range os.Args[1:] { + fmt.Printf("Arg %d is %s\n", i+1, a) + if a == argVal { + return true + } + } + return false +} + +func getWalletServerUrl() string { + return checkWalletUrl(GetFromEnv("WALLETSERVER_URL")) +} + +func GetToken() string { + if len(token) == 0 { + return LoadToken() + } + return token +} + +func LoadToken() string { + if existsInArgs(ciArgs) { + return PerformLogin() + } + if _, err := os.Stat(tokenFile); os.IsNotExist(err) { + log.Fatal("Error: No token file found: try running \"go run login.go\"") + } + tokenData, err := ioutil.ReadFile(tokenFile) + if err != nil { + log.Fatal("Error: Could not read token from token file", err) + } + token = string(tokenData) + return token +} + +func GetPubKey() string { + url := getWalletServerUrl() + "/api/v1/keys" + req, err := http.NewRequest(http.MethodGet, url, nil) + req.Header.Set("Authorization", "Bearer " + GetToken()) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Fatal("Error: Could not load public keys from wallet", err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Error: Could not read public keys", err) + } + var keypair service.KeysResponse + err = json.Unmarshal([]byte(body), &keypair) + if err != nil { + log.Fatal("Error: Could not convert public keys", err) + } + if len(keypair.Keys) == 0 { + log.Fatal("No public keys found, do you need to create one?") + } + + pk := keypair.Keys[0].Key + fmt.Println("pubkey: ", pk) + pubkey = pk + return pubkey +} + +func PerformLogin() string { + walletServerUrl := getWalletServerUrl() + walletName := os.Getenv("WALLET_NAME") + walletPassphrase := os.Getenv("WALLET_PASSPHRASE") + validUser := checkVar(walletName) + validPass := checkVar(walletPassphrase) + if existsInArgs(ciArgs) && !validUser { + log.Fatal("Error: Missing environment variable WALLET_NAME") + } + if existsInArgs(ciArgs) && !validPass { + log.Fatal("Error: Missing environment variable WALLET_PASSPHRASE") + } + if !validUser || !validPass { + reader := bufio.NewReader(os.Stdin) + + fmt.Print("Enter Vega wallet username: ") + username, err := reader.ReadString('\n') + if err != nil { + log.Fatal("Error: Could not read username from command line", err) + } + walletName = username + + fmt.Print("Vega wallet passphrase: ") + bytePassword, err := term.ReadPassword(syscall.Stdin) + if err != nil { + log.Fatal("Error: Could not read password from command line", err) + } + fmt.Println() + + walletPassphrase = string(bytePassword) + + walletName = strings.TrimRightFunc(walletName, func(c rune) bool { + //In windows newline is \r\n + return c == '\r' || c == '\n' + }) + } + + walletReq := &service.CreateLoginWalletRequest{Wallet: walletName, Passphrase: walletPassphrase} + payload, err := json.Marshal(walletReq) + if err != nil { + log.Fatal(err) + } + req, err := http.NewRequest( + http.MethodPost, + walletServerUrl + "/api/v1/auth/token", + bytes.NewBuffer(payload), + ) + + cli := &http.Client{} + resp, err := cli.Do(req) + if err != nil { + log.Fatal("Error logging in (1): " + err.Error()) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Error logging in (2): " + err.Error()) + } + + if resp.StatusCode != 200 { + log.Fatal("Error logging in (3): ", string(body)) + } + + var res service.TokenResponse + err = json.Unmarshal([]byte(body), &res) + if err != nil { + log.Fatal("Error logging in (4): " + err.Error()) + } + + if !existsInArgs(ciArgs) { + f, err := os.Create(tokenFile) + if err != nil { + log.Fatal("Error: Could not write token file to disk (1). " + err.Error()) + } + //err = f.Truncate(0) + //_, err = f.Seek(0, 0) + _, err = f.WriteString(res.Token) + if err != nil { + log.Fatal("Error: Could not write token file to disk (2). " + err.Error()) + } + fmt.Println("GetToken saved to \"token.temp\", done.") + } + + token = res.Token + return token +} + +func SignTransactionCommand(json string) ([]byte, error) { + token := LoadToken() + walletServerUrl := getWalletServerUrl() + req, err := http.NewRequest( + http.MethodPost, + walletServerUrl + "/api/v1/command/sync", + bytes.NewBufferString(json), + ) + req.Header.Add("Authorization", "Bearer " + token) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Fatal("Error: Sign Transaction command failed (1). " + err.Error()) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Error: Sign Transaction command failed (2). " + err.Error()) + } + + if resp.StatusCode != 200 { + log.Fatal("Error: Sign Transaction command failed (3). " + string(body)) + } + + return body, nil +} + +func SignTransactionDeprecated(json string) ([]byte, error) { + token := LoadToken() + walletServerUrl := getWalletServerUrl() + req, err := http.NewRequest( + http.MethodPost, + walletServerUrl + "/api/v1/messages", + bytes.NewBufferString(json), + ) + req.Header.Add("Authorization", "Bearer " + token) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Fatal("Error: Sign Transaction command failed (1). " + err.Error()) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Error: Sign Transaction command failed (2). " + err.Error()) + } + + if resp.StatusCode != 200 { + log.Fatal("Error: Sign Transaction command failed (3). " + string(body)) + } + + return body, nil +} + + +func checkWalletUrl(url string) string { + suffix := []string{"/api/v1/", "/api/v1", "/"} + for _, s := range suffix { + if strings.HasSuffix(url, s) { + fmt.Println("There's no need to add ", s, " to WALLETSERVER_URL. Removing it.") + return url[0 : len(url)-len(s)] + } + } + return url +} + +func checkVar(val string) bool { + return val != "" && val != "example" && val != ">>" && val != "e.g." +} \ No newline at end of file diff --git a/grpc/examples/go/login.go b/grpc/examples/go/login.go new file mode 100644 index 00000000..ba3bc1ed --- /dev/null +++ b/grpc/examples/go/login.go @@ -0,0 +1,13 @@ +package main + +import "github.com/vegaprotocol/api/grpc/examples/go/helpers" + +func main() { + // Perform login attempts to log in to the configured + // Vega wallet and get an access token for use when + // signing and interacting with the wallet + helpers.PerformLogin() + + // If there are --ci args passed when running the script + // then it will use the details from env vars directly +} diff --git a/grpc/examples/go/stream-events.go b/grpc/examples/go/stream-events.go new file mode 100644 index 00000000..c535b485 --- /dev/null +++ b/grpc/examples/go/stream-events.go @@ -0,0 +1,73 @@ +package main + +import ( + "context" + "fmt" + "io" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/events/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Request the identifier for a market + + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + marketID := markets.Markets[0].Id + fmt.Printf("Found market: %s \n", marketID) + + fmt.Println("Connecting to stream...") + + // __stream_events: + // Subscribe to the events bus stream for the marketID specified + // Required: type field - A collection of one or more event types e.g. BUS_EVENT_TYPE_ORDER. + // Required: batch_size field - Default: 0 - Total number of events to batch on server before sending to client. + // Optional: Market identifier - filter by market + // Party identifier - filter by party + // By default, all events on all markets for all parties will be returned on the stream. + // e.g. all_types = vac.events.BUS_EVENT_TYPE_ALL + eventType := v1.BusEventType_BUS_EVENT_TYPE_MARKET_TICK + event, err := dataClient.ObserveEventBus(context.Background()) + + done := make(chan bool) + go func() { + for { + resp, err := event.Recv() + + if err == io.EOF { + // read done. + close(done) + return + } + if err != nil { + panic(err) + } + fmt.Printf("Resp received: %s\n", &resp.Events) + } + }() + + observerEvent := api.ObserveEventBusRequest{Type: []v1.BusEventType{eventType}, MarketId: marketID} + event.Send(&observerEvent) + event.CloseSend() + + <-done //we will wait until all response is received + // :stream_events__ + fmt.Printf("finished") + +} diff --git a/grpc/examples/go/stream-marketdata.go b/grpc/examples/go/stream-marketdata.go new file mode 100644 index 00000000..de19ccd5 --- /dev/null +++ b/grpc/examples/go/stream-marketdata.go @@ -0,0 +1,64 @@ +package main + +import ( + "context" + "fmt" + "io" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/events/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Request the identifier for a market + + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + marketID := markets.Markets[0].Id + fmt.Printf("Found market: %s \n", marketID) + + fmt.Println("Connecting to stream...") + + eventType := v1.BusEventType_BUS_EVENT_TYPE_MARKET_TICK + event, err := dataClient.ObserveEventBus(context.Background()) + + done := make(chan bool) + go func() { + for { + resp, err := event.Recv() + + if err == io.EOF { + // read done. + close(done) + return + } + if err != nil { + panic(err) + } + fmt.Printf("Resp received: %s\n", &resp.Events) + } + }() + + observerEvent := api.ObserveEventBusRequest{Type: []v1.BusEventType{eventType}, MarketId: marketID} + event.Send(&observerEvent) + event.CloseSend() + + <-done //we will wait until all response is received + fmt.Printf("finished") + +} diff --git a/grpc/examples/go/stream-orders.go b/grpc/examples/go/stream-orders.go new file mode 100644 index 00000000..2931bba7 --- /dev/null +++ b/grpc/examples/go/stream-orders.go @@ -0,0 +1,71 @@ +package main + +import ( + "context" + "fmt" + "io" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/events/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Request the identifier for a market + + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + marketID := markets.Markets[0].Id + fmt.Printf("Found market: %s \n", marketID) + + fmt.Println("Connecting to stream...") + + // __stream_orders: + // Subscribe to the Orders stream for the marketID specified + // Optional: Market identifier - filter by market + // Party identifier - filter by party + // By default, all orders on all markets for all parties will be returned on the stream. + eventType := v1.BusEventType_BUS_EVENT_TYPE_ORDER + event, err := dataClient.ObserveEventBus(context.Background()) + + done := make(chan bool) + go func() { + for { + resp, err := event.Recv() + + if err == io.EOF { + // read done. + close(done) + return + } + if err != nil { + panic(err) + } + fmt.Printf("Resp received: %v\n", &resp.Events) + } + }() + + observerEvent := api.ObserveEventBusRequest{Type: []v1.BusEventType{eventType}, MarketId: marketID} + event.Send(&observerEvent) + event.CloseSend() + + <-done //we will wait until all response is received + // :stream_orders__ + fmt.Printf("finished") + +} diff --git a/grpc/examples/go/stream-trades.go b/grpc/examples/go/stream-trades.go new file mode 100644 index 00000000..f7f73ef7 --- /dev/null +++ b/grpc/examples/go/stream-trades.go @@ -0,0 +1,71 @@ +package main + +import ( + "context" + "fmt" + "io" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/events/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "google.golang.org/grpc" +) + +func main() { + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Request the identifier for a market + + request := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &request) + if err != nil { + panic(err) + } + marketID := markets.Markets[0].Id + fmt.Printf("Found market: %s \n", marketID) + + fmt.Println("Connecting to stream...") + + // __stream_trades: + // Subscribe to the Trades stream for the marketID specified + // Optional: Market identifier - filter by market + // Party identifier - filter by party + // By default, all trades on all markets for all parties will be returned on the stream. + eventType := v1.BusEventType_BUS_EVENT_TYPE_TRADE + event, err := dataClient.ObserveEventBus(context.Background()) + + done := make(chan bool) + go func() { + for { + resp, err := event.Recv() + + if err == io.EOF { + // read done. + close(done) + return + } + if err != nil { + panic(err) + } + fmt.Printf("Resp received: %v\n", &resp.Events) + } + }() + + observerEvent := api.ObserveEventBusRequest{Type: []v1.BusEventType{eventType}, MarketId: marketID} + event.Send(&observerEvent) + event.CloseSend() + + <-done //we will wait until all response is received + // :stream_trades__ + + fmt.Printf("finished") + +} diff --git a/grpc/examples/go/submit-amend-cancel-order.go b/grpc/examples/go/submit-amend-cancel-order.go new file mode 100644 index 00000000..d5910968 --- /dev/null +++ b/grpc/examples/go/submit-amend-cancel-order.go @@ -0,0 +1,202 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "time" + + "github.com/satori/go.uuid" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/commands/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // Get market + marketRequest := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &marketRequest) + if err != nil { + panic(err) + } + marketId := markets.Markets[0].Id + + // Get Blockchain time + // __get_expiry_time: + // Request the current blockchain time, calculate an expiry time + request := api.GetVegaTimeRequest{} + vegaTime, err := dataClient.GetVegaTime(context.Background(), &request) + if err != nil { + panic(err) + } + expireAt := vegaTime.Timestamp + (120 * 1e9) + + // :get_expiry_time__ + fmt.Printf("Blockchain time: %d\n", vegaTime.Timestamp) + fmt.Printf("Order expiration time: %d\n", expireAt) + + // __prepare_submit_order: + // Compose a submit order message + orderRef := fmt.Sprintf("%s-%s", pubkey, uuid.NewV4()) + orderSubmission := &v1.OrderSubmission{ + Size: 10, + Price: 1, + MarketId: marketId, + Side: proto.Side_SIDE_BUY, + TimeInForce: proto.Order_TIME_IN_FORCE_GTT, + Type: proto.Order_TYPE_LIMIT, + ExpiresAt: expireAt, + Reference: orderRef, + } + // :prepare_submit_order__ + + log.Printf("Order submission: %v\n", orderSubmission) + + // __sign_tx_order: + reqCmd, _ := json.Marshal(orderSubmission) + reqStr := fmt.Sprintf( + "{ \"pub_key\": \"%s\", \"propagate\": true, \"order_submission\": %s }", + pubkey, reqCmd) + + _, err = helpers.SignTransactionCommand(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_order__ + + fmt.Printf("Signed order and sent to Vega\n") + + // Wait for order submission to be included in a block + fmt.Printf("Waiting for blockchain...\n") + time.Sleep(4 * time.Second) + orderByRef := api.OrderByReferenceRequest{Reference: orderRef} + orderByRefResp, err := dataClient.OrderByReference(context.Background(), &orderByRef) + if err != nil { + panic(err) + } + + orderID := orderByRefResp.Order.Id + orderStatus := orderByRefResp.Order.Status.String() + fmt.Printf("Order processed. ID: %s, Status: %s\n", orderID, orderStatus) + + // Amend order + // __prepare_amend_order: + // Compose an amend order message + price := proto.Price{Value: 2} + orderAmendment := &v1.OrderAmendment{ + MarketId: marketId, + OrderId: orderID, + Price: &price, + TimeInForce: proto.Order_TIME_IN_FORCE_GTC, + } + // :prepare_amend_order__ + + log.Printf("Order amendment: %v\n", orderAmendment) + + // __sign_tx_amend: + reqCmd, _ = json.Marshal(orderAmendment) + reqStr = fmt.Sprintf( + "{ \"pub_key\": \"%s\", \"propagate\": true, \"order_amendment\": %s }", + pubkey, reqCmd) + + _, err = helpers.SignTransactionCommand(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_amend__ + + fmt.Printf("Signed order amendment and sent to Vega\n") + + // Wait for amendment to be included in a block + fmt.Printf("Waiting for blockchain...\n") + time.Sleep(4 * time.Second) + orderByRef = api.OrderByReferenceRequest{Reference: orderRef} + orderByRefResp, err = dataClient.OrderByReference(context.Background(), &orderByRef) + if err != nil { + panic(err) + } + + orderID = orderByRefResp.Order.Id + orderStatus = orderByRefResp.Order.Status.String() + orderSize := orderByRefResp.Order.Size + orderPrice := orderByRefResp.Order.Price + orderTif := orderByRefResp.Order.TimeInForce.String() + + fmt.Printf("Amended order:\n") + fmt.Printf("ID: %s, Status: %s, Price(Old): 1,\n", orderID, orderStatus) + fmt.Printf("Price(New): %d, Size(Old): 100, Size(New): %d\n", orderPrice, orderSize) + fmt.Printf("TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): %s,\n", orderTif) + + + // Cancel order + // __prepare_cancel_order_req1: + // 1 - Cancel single order for party (pubkey) + orderCancellation := &v1.OrderCancellation{ + OrderId: orderID, + MarketId: marketId, + } + // :prepare_cancel_order_req1__ + + // __prepare_cancel_order_req2: + // 2 - Cancel all orders on market for party (pubkey) + orderCancellation = &v1.OrderCancellation{ + MarketId: marketId, + } + // :prepare_cancel_order_req2__ + + // __prepare_cancel_order_req3: + // 3 - Cancel all orders on all markets for party (pubkey) + orderCancellation = &v1.OrderCancellation{} + // :prepare_cancel_order_req3__ + + + log.Printf("Order cancellation: %v\n", orderCancellation) + + // __sign_tx_cancel: + reqCmd, _ = json.Marshal(orderCancellation) + reqStr = fmt.Sprintf( + "{ \"pub_key\": \"%s\", \"propagate\": true, \"order_cancellation\": %s }", + pubkey, reqCmd) + + _, err = helpers.SignTransactionCommand(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_cancel__ + + fmt.Printf("Signed order cancellation request and sent to Vega\n") + + // Wait for amendment to be included in a block + fmt.Printf("Waiting for blockchain...\n") + time.Sleep(4 * time.Second) + orderByRef = api.OrderByReferenceRequest{Reference: orderRef} + orderByRefResp, err = dataClient.OrderByReference(context.Background(), &orderByRef) + if err != nil { + panic(err) + } + + orderID = orderByRefResp.Order.Id + orderStatus = orderByRefResp.Order.Status.String() + + fmt.Printf("Cancelled order:\n") + fmt.Printf("ID: %s, Status: %s\n", orderID, orderStatus) +} diff --git a/grpc/examples/go/submit-amend-pegged-order.go b/grpc/examples/go/submit-amend-pegged-order.go new file mode 100644 index 00000000..e0fb11ca --- /dev/null +++ b/grpc/examples/go/submit-amend-pegged-order.go @@ -0,0 +1,157 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "time" + + uuid "github.com/satori/go.uuid" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/commands/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "github.com/golang/protobuf/ptypes/wrappers" + "golang.org/x/net/context" + "google.golang.org/grpc" + +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + + // __get_market: + // Request the identifier for the market to place on + marketRequest := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &marketRequest) + if err != nil { + panic(err) + } + marketId := markets.Markets[0].Id + // :get_market__ + + // __get_expiry_time: + // Request the current blockchain time, calculate an expiry time + request := api.GetVegaTimeRequest{} + vegaTime, err := dataClient.GetVegaTime(context.Background(), &request) + + expireAt := vegaTime.Timestamp + (120 * 1e9) + // :get_expiry_time__ + + fmt.Printf("Blockchain time: %d\n", vegaTime.Timestamp) + fmt.Printf("Order expiration time: %d\n", expireAt) + + // __prepare_submit_pegged_order: + // Compose the submit order message with a pegged BUY order + orderRef := fmt.Sprintf("%s-%s", pubkey, uuid.NewV4()) + peggedOrder := proto.PeggedOrder{ + Offset: -5, + Reference: proto.PeggedReference_PEGGED_REFERENCE_MID, + } + orderSubmission := &v1.OrderSubmission{ + Size: 1, + Price: 100000, + MarketId: marketId, + Side: proto.Side_SIDE_BUY, + TimeInForce: proto.Order_TIME_IN_FORCE_GTT, + Type: proto.Order_TYPE_LIMIT, + ExpiresAt: expireAt, + PeggedOrder: &peggedOrder, + Reference: orderRef, + } + // :prepare_submit_pegged_order__ + + log.Printf("Order submission: %v\n", orderSubmission) + + // __sign_tx_order: + reqCmd, _ := json.Marshal(orderSubmission) + reqStr := fmt.Sprintf( + "{ \"pub_key\": \"%s\", \"propagate\": true, \"order_submission\": %s }", + pubkey, reqCmd) + + _, err = helpers.SignTransactionCommand(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_order__ + + fmt.Printf("Signed pegged order and sent to Vega\n") + + // Wait for order submission to be included in a block + fmt.Printf("Waiting for blockchain...\n") + time.Sleep(4 * time.Second) + orderByRef := api.OrderByReferenceRequest{Reference: orderRef} + + orderByRefResp, err := dataClient.OrderByReference(context.Background(), &orderByRef) + if err != nil { + panic(err) + } + + orderID := orderByRefResp.Order.Id + orderStatus := orderByRefResp.Order.Status.String() + fmt.Printf("Pegged order processed. ID: %s, Status: %s\n", orderID, orderStatus) + + // __prepare_amend_pegged_order: + // Compose the amend pegged order message + var peggedOffset wrappers.Int64Value + peggedOffset.Value = -100 + + orderAmendment := &v1.OrderAmendment{ + MarketId: marketId, + OrderId: orderID, + SizeDelta: -25, + TimeInForce: proto.Order_TIME_IN_FORCE_GTC, + PeggedReference: proto.PeggedReference_PEGGED_REFERENCE_BEST_BID, + PeggedOffset: &peggedOffset, + } + // :prepare_amend_pegged_order__ + log.Printf("Order amendment: %v\n", orderAmendment) + + // __sign_tx_amend: + reqCmd, _ = json.Marshal(orderAmendment) + reqStr = fmt.Sprintf( + "{ \"pub_key\": \"%s\", \"propagate\": true, \"order_amendment\": %s }", + pubkey, reqCmd) + + _, err = helpers.SignTransactionCommand(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_amend__ + + fmt.Printf("Signed pegged order amendment and sent to Vega\n") + + // Wait for amendment to be included in a block + fmt.Printf("Waiting for blockchain...\n") + time.Sleep(4 * time.Second) + orderByRef = api.OrderByReferenceRequest{Reference: orderRef} + orderByRefResp, err = dataClient.OrderByReference(context.Background(), &orderByRef) + if err != nil { + panic(err) + } + + orderID = orderByRefResp.Order.Id + orderStatus = orderByRefResp.Order.Status.String() + oderSize := orderByRefResp.Order.Size + orderTif := orderByRefResp.Order.TimeInForce.String() + peggedOrderRef := orderByRefResp.Order.PeggedOrder + + fmt.Printf("Amended pegged order:\n") + fmt.Printf("Pegged order processed. ID: %s, Status: %s\n", orderID, orderStatus) + fmt.Printf("Size(Old): 50, Size(New): %d,\n", oderSize) + fmt.Printf("TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): %s,\n", orderTif) + fmt.Printf("Pegged at:\n%s\n", peggedOrderRef) +} diff --git a/grpc/examples/go/submit-order.go b/grpc/examples/go/submit-order.go new file mode 100644 index 00000000..841632ef --- /dev/null +++ b/grpc/examples/go/submit-order.go @@ -0,0 +1,74 @@ +package main + +import ( + "encoding/base64" + "fmt" + + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto" + "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/api" + v1 "github.com/vegaprotocol/api/grpc/clients/go/generated/code.vegaprotocol.io/vega/proto/commands/v1" + "github.com/vegaprotocol/api/grpc/examples/go/helpers" + + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +func main() { + // Helpers include logic to authenticate with a Vega wallet service + // including token storage/public key operations/signing of commands + // visit ./helpers/wallet.go for more detail + pubkey := helpers.GetPubKey() + + nodeURLGrpc := helpers.GetFromEnv("NODE_URL_GRPC") + conn, err := grpc.Dial(nodeURLGrpc, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + dataClient := api.NewTradingDataServiceClient(conn) + tradingClient := api.NewTradingServiceClient(conn) + + // __get_market: + // Get a list of markets + marketRequest := api.MarketsRequest{} + markets, err := dataClient.Markets(context.Background(), &marketRequest) + if err != nil { + panic(err) + } + marketId := markets.Markets[0].Id + // :get_market__ + + // __prepare_order: + // Vega node: Prepare the SubmitOrder + orderSubmission := v1.OrderSubmission{ + Size: 1, + Price: 100000, + MarketId: marketId, + Side: proto.Side_SIDE_BUY, + TimeInForce: proto.Order_TIME_IN_FORCE_GTC, + Type: proto.Order_TYPE_LIMIT, + } + + order := api.PrepareSubmitOrderRequest{Submission: &orderSubmission} + prepareResponse, err := tradingClient.PrepareSubmitOrder(context.Background(), &order) + if err != nil { + panic(err) + } + // :prepare_order__ + + // Sign the prepared transaction + data := prepareResponse.Blob + sEnc := base64.StdEncoding.EncodeToString([]byte(data)) + + // __sign_tx_order: + reqStr := fmt.Sprintf( + "{ \"pubKey\": \"%s\", \"propagate\": true, \"tx\": \"%s\" }", + pubkey, sEnc) + + _, err = helpers.SignTransactionDeprecated(reqStr) + if err != nil { + panic(err) + } + // :sign_tx_order__ +} diff --git a/grpc/examples/python/get-accounts.py b/grpc/examples/python/get-accounts.py new file mode 100755 index 00000000..0b428344 --- /dev/null +++ b/grpc/examples/python/get-accounts.py @@ -0,0 +1,77 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) + +Responses: +- response-examples.txt +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +print("Token:", token) + +############################################################################### +# M A R K E T A C C O U N T S # +############################################################################### + +# Request a list of markets and select the first one +req = vac.api.trading.MarketsRequest() +markets = data_client.Markets(req).markets +marketID = markets[0].id + +assert marketID != "" +print(f"Market found: {marketID}") + +# __get_accounts_by_market: +# Request a list of accounts for a market on a Vega network +request = vac.api.trading.MarketAccountsRequest(market_id=marketID) +market_accounts = data_client.MarketAccounts(request) +print("Market accounts:\n{}".format(market_accounts)) +# :get_accounts_by_market__ + +############################################################################### +# P A R T Y A C C O U N T S # +############################################################################### + +# __get_accounts_by_party: +# Request a list of accounts for a party (pubkey) on a Vega network +request = vac.api.trading.PartyAccountsRequest(party_id=pubkey) +party_accounts = data_client.PartyAccounts(request) +print("Party accounts:\n{}".format(party_accounts)) +# :get_accounts_by_party__ + +############################################################################### +# P A R T Y P O S I T I O N S # +############################################################################### + +# __get_positions_by_party: +# Request a list of positions for a party (pubkey) on a Vega network +request = vac.api.trading.PositionsByPartyRequest(party_id=pubkey) +party_positions = data_client.PositionsByParty(request) +print("Party positions:\n{}".format(party_positions)) +# :get_positions_by_party__ diff --git a/grpc/examples/python/get-fees-margins-estimate.py b/grpc/examples/python/get-fees-margins-estimate.py new file mode 100644 index 00000000..eca6082c --- /dev/null +++ b/grpc/examples/python/get-fees-margins-estimate.py @@ -0,0 +1,93 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +# Vega wallet interaction helper, please see login.py for more detail +from login import token, pubkey + +# Load gRPC Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + +# Vega gRPC clients for reading/writing data +data_client = vac.VegaTradingDataClient(node_url_grpc) + +print("Token:", token) + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +marketID = markets[0].id +# :get_market__ + +assert marketID != "" +print(f"Market found: {marketID}") + +############################################################################### +# F E E E S T I M A T I O N # +############################################################################### + +# __get_fees_estimate: +# Request to estimate trading fees on a Vega network +estimate = vac.api.trading.EstimateFeeRequest( + order=vac.vega.Order( + market_id=marketID, + party_id=pubkey, + price=100000, + size=100, + side=vac.vega.Side.SIDE_BUY, + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTC, + type=vac.vega.Order.Type.TYPE_LIMIT, + ) +) +estimated_fees = data_client.EstimateFee(estimate) +print("FeeEstimates:\n{}".format(estimated_fees)) +# :get_fees_estimate__ + +############################################################################### +# M A R G I N E S T I M A T I O N # +############################################################################### + +# __get_margins_estimate: +# Request to estimate trading margin on a Vega network +estimate = vac.api.trading.EstimateMarginRequest( + order=vac.vega.Order( + market_id=marketID, + party_id=pubkey, + price=600000, + size=10, + side=vac.vega.Side.SIDE_BUY, + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTC, + type=vac.vega.Order.Type.TYPE_LIMIT, + ) +) +estimated_margins = data_client.EstimateMargin(estimate) +print("MarginEstimates:\n{}".format(estimated_margins)) +# :get_margins_estimate__ diff --git a/grpc/examples/python/get-markets-and-marketdata.py b/grpc/examples/python/get-markets-and-marketdata.py new file mode 100644 index 00000000..de40d8b3 --- /dev/null +++ b/grpc/examples/python/get-markets-and-marketdata.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +# __get_markets: +# Request a list of markets available on the specified Vega Network +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +print("Markets:\n{}".format(markets)) +# :get_markets__ + +market_id = markets[0].id +assert market_id != "" + +# __get_market_data: +# Request the market data for a market on a Vega network +market_data_request = vac.api.trading.MarketDataByIDRequest( + market_id=market_id +) +market_data = data_client.MarketDataByID(market_data_request) +print("MarketData:\n{}".format(market_data)) +# :get_market_data__ diff --git a/grpc/examples/python/get-network-parameters.py b/grpc/examples/python/get-network-parameters.py new file mode 100644 index 00000000..1c3b3554 --- /dev/null +++ b/grpc/examples/python/get-network-parameters.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac + +# Vega gRPC clients for reading/writing data +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +############################################################################### +# N E T W O R K P A R A M E T E R S # +############################################################################### + +# __get_network_params: +# Request a list of network parameters configured on a Vega network +request = vac.api.trading.NetworkParametersRequest() +network_params = data_client.NetworkParameters(request) +print("Network Parameter:\n{}".format(network_params)) +# :get_network_params__ diff --git a/grpc/examples/python/get-order-by-reference.py b/grpc/examples/python/get-order-by-reference.py new file mode 100644 index 00000000..6de29fe4 --- /dev/null +++ b/grpc/examples/python/get-order-by-reference.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + +# __get_order_by_ref: +# Request an order by reference on a Vega network +# Note: This is an example and order reference will be provided in the response +# from a prepareSubmitOrder request in the field named `submitID` or similar. +reference = "15b757d2-9dcd-4442-81da-18c709c8d97e" +data_client = vac.VegaTradingDataClient(node_url_grpc) +order_by_ref_request = vac.api.trading.OrderByReferenceRequest( + reference=reference +) +response = data_client.OrderByReference(order_by_ref_request) +print("OrderByReference:\n{}".format(response)) +# :get_order_by_ref__ diff --git a/grpc/examples/python/get-orders-and-trades-for-market.py b/grpc/examples/python/get-orders-and-trades-for-market.py new file mode 100644 index 00000000..8b31bfbe --- /dev/null +++ b/grpc/examples/python/get-orders-and-trades-for-market.py @@ -0,0 +1,50 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +market_id = markets[0].id +assert market_id != "" + +# __get_orders_for_market: +# Request a list of orders by market on a Vega network +orders_by_market_request = vac.api.trading.OrdersByMarketRequest( + market_id=market_id +) +orders_response = data_client.OrdersByMarket(orders_by_market_request) +print("OrdersByMarket:\n{}".format(orders_response)) +# :get_orders_for_market__ + +# __get_trades_for_market: +# Request a list of trades by market on a Vega network +trades_by_market_request = vac.api.trading.TradesByMarketRequest( + market_id=market_id +) +trades_response = data_client.TradesByMarket(trades_by_market_request) +print("TradesByMarket:\n{}".format(trades_response)) +# :get_trades_for_market__ diff --git a/grpc/examples/python/get-orders-and-trades-for-party.py b/grpc/examples/python/get-orders-and-trades-for-party.py new file mode 100644 index 00000000..fd0aace0 --- /dev/null +++ b/grpc/examples/python/get-orders-and-trades-for-party.py @@ -0,0 +1,52 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (gRPC) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +print("Token:", token) + +# __get_orders_for_party: +# Request a list of orders by party (pubKey) +orders_by_party_request = vac.api.trading.OrdersByPartyRequest( + party_id=pubkey +) +orders_response = data_client.OrdersByParty(orders_by_party_request) +print("OrdersByParty:\n{}".format(orders_response)) +# :get_orders_for_party__ + +# __get_trades_for_party: +# Request a list of trades by party (pubKey) +trades_by_party_request = vac.api.trading.TradesByPartyRequest( + party_id=pubkey +) +trades_response = data_client.TradesByParty(trades_by_party_request) +print("TradesByParty:\n{}".format(trades_response)) +# :get_trades_for_party__ diff --git a/grpc/examples/python/get-parties.py b/grpc/examples/python/get-parties.py new file mode 100755 index 00000000..abfc4d15 --- /dev/null +++ b/grpc/examples/python/get-parties.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) + +Responses: +- response-examples.txt +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import os +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = os.getenv("NODE_URL_GRPC") + +# __get_parties: +# Request a list of parties trading on a Vega network +data_client = vac.VegaTradingDataClient(node_url_grpc) +req = vac.api.trading.PartiesRequest() +response = data_client.Parties(req) +print("Parties:\n{}".format(response)) +# :get_parties__ diff --git a/grpc/examples/python/get-statistics.py b/grpc/examples/python/get-statistics.py new file mode 100644 index 00000000..1deb8dad --- /dev/null +++ b/grpc/examples/python/get-statistics.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import os + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = os.getenv("NODE_URL_GRPC") + +# __get_statistics: +# Request the statistics for a node on Vega +data_client = vac.VegaTradingDataClient(node_url_grpc) +response = data_client.Statistics(vac.api.trading.StatisticsRequest()) +print("Statistics:\n{}".format(response)) +# :get_statistics__ diff --git a/grpc/examples/python/get-time.py b/grpc/examples/python/get-time.py new file mode 100755 index 00000000..a7dc7e40 --- /dev/null +++ b/grpc/examples/python/get-time.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import os + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = os.getenv("NODE_URL_GRPC") + +# __get_time: +# Request the latest timestamp in nanoseconds since epoch from the Vega network +data_client = vac.VegaTradingDataClient(node_url_grpc) + +# The "timestamp" field contains the resulting data we need. +vega_time = data_client.GetVegaTime(vac.api.trading.GetVegaTimeRequest()) +print("Vega time:\n{}".format(vega_time)) +# :get_time__ diff --git a/grpc/examples/python/get-trades-for-order.py b/grpc/examples/python/get-trades-for-order.py new file mode 100644 index 00000000..fe359ef9 --- /dev/null +++ b/grpc/examples/python/get-trades-for-order.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +# __get_trades_for_order: +# Request a list of trades for a specific order on a Vega network +orderID = "V0000929211-0046318720" +trades_by_order_request = vac.api.trading.TradesByOrderRequest( + # Note: orderID has capitalised ID in TradesByOrderRequest + orderID=orderID +) +trades_response = data_client.TradesByOrder(trades_by_order_request) +print("TradesByOrderID:\n{}".format(trades_response)) +# :get_trades_for_order__ diff --git a/grpc/examples/python/helpers.py b/grpc/examples/python/helpers.py index 9aa3101d..5a78f477 100644 --- a/grpc/examples/python/helpers.py +++ b/grpc/examples/python/helpers.py @@ -17,7 +17,7 @@ def check_var(val: str) -> bool: """ Return true if the value is ok. """ - if val == "": + if val is None or val == "": return False if invalid(val): return False diff --git a/grpc/examples/python/login.py b/grpc/examples/python/login.py new file mode 100644 index 00000000..27e053e7 --- /dev/null +++ b/grpc/examples/python/login.py @@ -0,0 +1,73 @@ +import requests +import os.path +import json +import sys +import helpers + +ci_args = "--ci" +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") + + +def load_token(): + if ci_args in sys.argv: + return perform_login() + # login will call exit with appropriate code + if not os.path.isfile("token.temp"): + print('Error: No token file found: try running "python3 login.py"') + exit(1) + with open("token.temp", "r") as token_file: + return json.load(token_file)["token"] + + +def get_pubkey(token): + auth_headers = {"Authorization": "Bearer " + token} + response = requests.get( + wallet_server_url + "/api/v1/keys", headers=auth_headers + ) + if response.status_code != 200: + print("Error listing keys: " + response.text) + exit(1) + keys = response.json()["keys"] + if len(keys) < 1: + print("Error: No keys found, use Vega Console" + + " or Vega Wallet CLI to create one") + exit(1) + return keys[0]["pub"], auth_headers + + +def perform_login(): + import getpass + wallet_name = os.getenv("WALLET_NAME") + wallet_passphrase = os.getenv("WALLET_PASSPHRASE") + valid_user = helpers.check_var(wallet_name) + valid_pass = helpers.check_var(wallet_passphrase) + if ci_args in sys.argv and not valid_user: + print("Error: Missing environment variable WALLET_NAME") + exit(1) + if ci_args in sys.argv and not valid_pass: + print("Error: Missing environment variable WALLET_PASSPHRASE") + exit(1) + if not valid_user or not valid_pass: + wallet_name = input("Enter Vega wallet username: ") + wallet_passphrase = getpass.getpass("Vega wallet passphrase: ") + req = {"wallet": wallet_name, "passphrase": wallet_passphrase} + response = requests.post( + wallet_server_url + "/api/v1/auth/token", json=req + ) + if response.status_code != 200: + print("Error logging in: " + response.text) + exit(1) + if ci_args not in sys.argv: + with open("token.temp", "w") as token_file: + json.dump(response.json(), token_file) + print('Token saved to "token.temp", done.') + return response.json()["token"] + + +if __name__ == "__main__": + perform_login() + exit(0) + + +token = load_token() +pubkey, auth_headers = get_pubkey(token) diff --git a/grpc/examples/python/manage-proposals.py b/grpc/examples/python/manage-proposals.py new file mode 100755 index 00000000..cf0331e9 --- /dev/null +++ b/grpc/examples/python/manage-proposals.py @@ -0,0 +1,76 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) + +Responses: +- response-examples.txt +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load gRPC Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + +print(token) + +############################################################################### +# L I S T P R O P O S A L S # +############################################################################### + +# __get_proposals: +# Request a list of proposals on a Vega network +request = vac.api.trading.GetProposalsRequest() +proposals = data_client.GetProposals(request) +print("Proposals:\n{}".format(proposals)) +# :get_proposals__ + +proposalID = proposals.data[0].proposal.id +assert proposalID != "" +print(f"Proposal found: {proposalID}") + +############################################################################### +# P R O P O S A L D E T A I L S # +############################################################################### + +# __get_proposal_detail: +# Request results of a specific proposal on a Vega network +request = vac.api.trading.GetProposalByIDRequest(proposal_id=proposalID) +proposal = data_client.GetProposalByID(request) +print("Proposal:\n{}".format(proposal)) +# :get_proposal_detail__ + +############################################################################### +# P A R T Y P R O P O S A L S # +############################################################################### + +# __get_proposals_by_party: +# Request a list of proposals for a party (pubkey) on a Vega network +request = vac.api.trading.GetProposalsByPartyRequest(party_id=pubkey) +party_proposals = data_client.GetProposalsByParty(request) +print("Party proposals:\n{}".format(party_proposals)) +# :get_proposals_by_party__ diff --git a/grpc/examples/python/stream-events.py b/grpc/examples/python/stream-events.py new file mode 100644 index 00000000..b112a86e --- /dev/null +++ b/grpc/examples/python/stream-events.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC (node): Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import queue +import signal +import sys +import helpers + +# __import_client: +import vegaapiclient as vac +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :import_client__ + + +def signal_handler(sig, frame): + print('Exit requested.') + sys.exit(0) + + +signal.signal(signal.SIGINT, signal_handler) + +# __get_market: +# Request the identifier for a market +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +market_id = markets[0].id +# :get_market__ + +print("Found market:") +print(market_id) + +print("Connecting to stream...") + +# __stream_events: +# Subscribe to the events bus stream for the marketID specified +# Required: type field +# - A collection of one or more event types e.g. BUS_EVENT_TYPE_ORDER. +# Required: batch_size field +# - Default: 0 +# - Total number of events to batch on server before sending to client. +# Optional: Market identifier - filter by market +# Party identifier - filter by party +# By default, all events on all markets for all +# parties will be returned on the stream. +# e.g. all_types = vac.events.BUS_EVENT_TYPE_ALL +event_types = vac.events.BUS_EVENT_TYPE_MARKET_TICK +subscribe_events_request = vac.api.trading.ObserveEventBusRequest( + batch_size=0, type=[event_types], market_id=market_id +) +send_queue = queue.SimpleQueue() +stream = data_client.ObserveEventBus(iter(send_queue.get, None)) +send_queue.put_nowait(subscribe_events_request) +for stream_resp in stream: + for events in stream_resp.events: + # All events (as per request filter) arriving + # over the channel/stream will be printed + print(events) +# :stream_events__ + +print("Stream disconnected.") diff --git a/grpc/examples/python/stream-orders-by-reference.py b/grpc/examples/python/stream-orders-by-reference.py new file mode 100644 index 00000000..324121db --- /dev/null +++ b/grpc/examples/python/stream-orders-by-reference.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC (node): Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import signal +import sys +import helpers + +# __import_client: +import vegaapiclient as vac +# :import_client__ + + +def signal_handler(sig, frame): + print('Exit requested.') + sys.exit(0) + + +signal.signal(signal.SIGINT, signal_handler) + +# __create_client: +# Create a Vega gRPC data client +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :create_client__ + +# __stream_orders_by_ref: +# Stream orders by reference on a Vega network +# Note: This is an example and order reference will be provided in the response +# from a prepareSubmitOrder request in the field named `submitID` or similar. +reference = "4617844f-6fab-4cf6-8852-e29dbd96e5f1" +pubkey = "94c21a5bfc212c0b4ee6e3593e8481559972ad31f1fb453491f255e72bdb6fdb" +subscribe_request = vac.api.trading.OrdersSubscribeRequest(party_id=pubkey) +for stream_resp in data_client.OrdersSubscribe(subscribe_request): + for order in stream_resp.orders: + # Check orders arriving over the channel/stream for reference + if order.reference == reference: + # Order with reference found + print(order) +# :stream_orders_by_ref__ diff --git a/grpc/examples/python/stream-orders.py b/grpc/examples/python/stream-orders.py new file mode 100644 index 00000000..f4d886ad --- /dev/null +++ b/grpc/examples/python/stream-orders.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC (node): Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import signal +import sys +import helpers + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + + +def signal_handler(sig, frame): + print('Exit requested.') + sys.exit(0) + + +signal.signal(signal.SIGINT, signal_handler) + +# __create_client: +# Create a Vega gRPC data client +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :create_client__ + +# __find_market: +# Get a list of markets, and select the first market returned +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +market_id = markets[0].id +# :find_market__ + +# __stream_orders: +# Subscribe to the Orders stream for the marketID specified +# Optional: Market identifier - filter by market +# Party identifier - filter by party +# By default, all orders on all markets for all +# parties will be returned on the stream. +subscribe_request = vac.api.trading.OrdersSubscribeRequest(market_id=market_id) +for stream_resp in data_client.OrdersSubscribe(subscribe_request): + for order in stream_resp.orders: + # All orders arriving over the channel/stream will be printed + print(order) +# :stream_orders__ diff --git a/grpc/examples/python/stream-trades.py b/grpc/examples/python/stream-trades.py new file mode 100644 index 00000000..3b190b24 --- /dev/null +++ b/grpc/examples/python/stream-trades.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (gRPC) + +Apps/Libraries: +- gRPC (node): Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import os +import signal +import sys + +# __import_client: +import vegaapiclient as vac +# :import_client__ + +node_url_grpc = os.getenv("NODE_URL_GRPC") + + +def signal_handler(sig, frame): + print('Exit requested.') + sys.exit(0) + + +signal.signal(signal.SIGINT, signal_handler) + +# __create_client: +# Create a Vega gRPC data client +data_client = vac.VegaTradingDataClient(node_url_grpc) +# :create_client__ + +# __find_market: +# Get a list of markets, and select the first market returned +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +market_id = markets[0].id +# :find_market__ + +# __stream_trades: +# Subscribe to the Trades stream for the marketID specified +# Optional: Market identifier - filter by market +# Party identifier - filter by party +# By default, all trades on all markets for all parties will be returned +subscribe_request = vac.api.trading.TradesSubscribeRequest(market_id=market_id) +for stream_resp in data_client.TradesSubscribe(subscribe_request): + for trade in stream_resp.trades: + # All trades arriving over the channel/stream will be printed + print(trade) +# :stream_trades__ diff --git a/grpc/examples/python/submit-amend-cancel-order.py b/grpc/examples/python/submit-amend-cancel-order.py new file mode 100644 index 00000000..cc882584 --- /dev/null +++ b/grpc/examples/python/submit-amend-cancel-order.py @@ -0,0 +1,247 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import base64 +import helpers +import time +import requests + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# __import_client: +import vegaapiclient as vac + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + +# Vega gRPC clients for reading/writing data +data_client = vac.VegaTradingDataClient(node_url_grpc) +trading_client = vac.VegaTradingClient(node_url_grpc) +# :import_client__ + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +marketID = markets[0].id +# :get_market__ + +assert marketID != "" +print(f"Market found: {marketID}") + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_expiry_time: +# Request the current blockchain time, calculate an expiry time +time_request = vac.api.trading.GetVegaTimeRequest() +blockchain_time = data_client.GetVegaTime(time_request).timestamp +expiresAt = int(blockchain_time + 120 * 1e9) # expire in 2 minutes +# :get_expiry_time__ + +assert blockchain_time > 0 +print(f"Blockchain time: {blockchain_time}") + +############################################################################### +# S U B M I T O R D E R # +############################################################################### + +# __prepare_submit_order: +# Prepare a submit order message +order = vac.api.trading.PrepareSubmitOrderRequest( + submission=vac.commands.v1.commands.OrderSubmission( + market_id=marketID, + # price is an integer. For example 123456 is a price of 1.23456, + # assuming 5 decimal places. + price=1, + side=vac.vega.Side.SIDE_BUY, + size=10, + expires_at=expiresAt, + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTT, + type=vac.vega.Order.Type.TYPE_LIMIT, + ) +) +prepared_order = trading_client.PrepareSubmitOrder(order) +# :prepare_submit_order__ + +order_ref = prepared_order.submit_id +print(f"Prepared order, ref: {order_ref}") + +# __sign_tx_order: +# Sign the prepared transaction +# Note: Setting propagate to true will submit to a Vega node +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +# :sign_tx_order__ + +print("Signed order and sent to Vega") + +# Wait for order submission to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +order_ref_req = vac.api.trading.OrderByReferenceRequest(reference=order_ref) +response = data_client.OrderByReference(order_ref_req) +orderID = response.order.id +orderStatus = helpers.enum_to_str(vac.vega.Order.Status, response.order.status) +createVersion = response.order.version +orderReason = response.order.reason +print(f"Order processed, ID: {orderID}, Status: {orderStatus}, " + + f"Version: {createVersion}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +############################################################################### +# A M E N D O R D E R # +############################################################################### + +# __prepare_amend_order: +# Prepare the amend order message +amend = vac.commands.v1.commands.OrderAmendment( + market_id=marketID, + order_id=orderID, + price=vac.vega.Price(value=2), + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTC, +) +order = vac.api.trading.PrepareAmendOrderRequest(amendment=amend) +prepared_order = trading_client.PrepareAmendOrder(order) +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +# :prepare_amend_order__ + +print(f"Amendment prepared for order ID: {orderID}") + +# __sign_tx_amend: +# Sign the prepared order transaction for amendment +# Note: Setting propagate to true will also submit to a Vega node +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +# :sign_tx_amend__ + +print("Signed amendment and sent to Vega") + +# Wait for amendment to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +order_id_request = vac.api.trading.OrderByIDRequest(order_id=orderID) +response = data_client.OrderByID(order_id_request) + +orderID = response.order.id +orderPrice = response.order.price +orderSize = response.order.size +orderTif = helpers.enum_to_str( + vac.vega.Order.TimeInForce, response.order.time_in_force +) +orderStatus = helpers.enum_to_str( + vac.vega.Order.Status, response.order.status +) +orderVersion = response.order.version +orderReason = response.order.reason + +print("Amended Order:") +print(f"ID: {orderID}, Status: {orderStatus}, Price(Old): 1, " + f"Price(New): {orderPrice}, Size(Old): 100, Size(New): {orderSize}, " + f"TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): {orderTif}, " + f"Version(Old): {createVersion}, Version(new): {orderVersion}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +############################################################################### +# C A N C E L O R D E R S # +############################################################################### + +# Select the mode to cancel orders from the following +# (comment out others), default = 3 + +# __prepare_cancel_order_req1: +# 1 - Cancel single order for party (pubkey) +cancel = vac.commands.v1.commands.OrderCancellation( + # Include party, market and order identifier fields to cancel single order. + market_id=marketID, + order_id=orderID, +) +# :prepare_cancel_order_req1__ + +# __prepare_cancel_order_req2: +# 2 - Cancel all orders on market for party (pubkey) +cancel = vac.commands.v1.commands.OrderCancellation( + # Only include party & market identifier fields. + market_id=marketID +) +# :prepare_cancel_order_req2__ + +# __prepare_cancel_order_req3: +# 3 - Cancel all orders on all markets for party (pubkey) +cancel = vac.commands.v1.commands.OrderCancellation() +# :prepare_cancel_order_req3__ + +# __prepare_cancel_order: +# Prepare the cancel order message +order = vac.api.trading.PrepareCancelOrderRequest(cancellation=cancel) +prepared_order = trading_client.PrepareCancelOrder(order) +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +# :prepare_cancel_order__ + +print(f"Cancellation prepared for order ID: {orderID}") + +# __sign_tx_cancel: +# Sign the prepared order transaction for cancellation +# Note: Setting propagate to true will submit to a Vega node +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +# :sign_tx_cancel__ + +print("Signed cancellation and sent to Vega") + +# Wait for cancellation to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +order_ref_req = vac.api.trading.OrderByReferenceRequest(reference=order_ref) +response = data_client.OrderByReference(order_ref_req) +orderStatus = helpers.enum_to_str(vac.vega.Order.Status, response.order.status) +orderReason = response.order.reason + +print("Cancelled Order:") +print(f"ID: {orderID}, Status: {orderStatus}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +# Completed. diff --git a/grpc/examples/python/submit-amend-pegged-order.py b/grpc/examples/python/submit-amend-pegged-order.py new file mode 100644 index 00000000..124fb240 --- /dev/null +++ b/grpc/examples/python/submit-amend-pegged-order.py @@ -0,0 +1,195 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import base64 +import helpers +import time +import requests + +from google.protobuf.wrappers_pb2 import Int64Value + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + + +# __import_client: +import vegaapiclient as vac + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + +# Vega gRPC clients for reading/writing data +data_client = vac.VegaTradingDataClient(node_url_grpc) +trading_client = vac.VegaTradingClient(node_url_grpc) +# :import_client__ + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +marketID = markets[0].id +# :get_market__ + +assert marketID != "" +print(f"Market found: {marketID}") + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_expiry_time: +# Request the current blockchain time, calculate an expiry time +time_req = vac.api.trading.GetVegaTimeRequest() +blockchain_time = data_client.GetVegaTime(time_req).timestamp +expiresAt = int(blockchain_time + 120 * 1e9) # expire in 2 minutes +# :get_expiry_time__ + +assert blockchain_time > 0 +print(f"Blockchain time: {blockchain_time}") + +############################################################################### +# S U B M I T P E G G E D O R D E R # +############################################################################### + +# __prepare_submit_pegged_order: +# Prepare a submit order message with a pegged BUY order +order = vac.api.trading.PrepareSubmitOrderRequest( + submission=vac.commands.v1.commands.OrderSubmission( + market_id=marketID, + side=vac.vega.Side.SIDE_BUY, + size=50, + expires_at=expiresAt, + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTT, + type=vac.vega.Order.Type.TYPE_LIMIT, + pegged_order=vac.vega.PeggedOrder( + offset=-5, + reference=vac.vega.PEGGED_REFERENCE_MID + ) + ) +) +prepared_order = trading_client.PrepareSubmitOrder(order) +# :prepare_submit_pegged_order__ + +order_ref = prepared_order.submit_id +print(f"Prepared pegged order, ref: {order_ref}") + +# __sign_tx_pegged_order: +# Sign the prepared pegged order transaction +# Note: Setting propagate to true will submit to a Vega node +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +# :sign_tx_pegged_order__ + +print("Signed pegged order and sent to Vega") + +# Wait for order submission to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +order_ref_req = vac.api.trading.OrderByReferenceRequest(reference=order_ref) +response = data_client.OrderByReference(order_ref_req) +orderID = response.order.id +orderStatus = helpers.enum_to_str(vac.vega.Order.Status, response.order.status) +createVersion = response.order.version +orderReason = response.order.reason + +print(f"\nPegged order processed, ID: {orderID}, " + + f"Status: {orderStatus}, Version: {createVersion}") + +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") +else: + print(f"Pegged at:\n{response.order.pegged_order}") + +############################################################################### +# A M E N D P E G G E D O R D E R # +############################################################################### + +# __prepare_amend_pegged_order: +# Prepare the amend pegged order message +amend = vac.commands.v1.commands.OrderAmendment( + market_id=marketID, + order_id=orderID, + size_delta=-25, + time_in_force=vac.vega.Order.TimeInForce.TIME_IN_FORCE_GTC, + pegged_reference=vac.vega.PEGGED_REFERENCE_BEST_BID, + pegged_offset=Int64Value(value=-100) +) +order = vac.api.trading.PrepareAmendOrderRequest(amendment=amend) +prepared_order = trading_client.PrepareAmendOrder(order) +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +# :prepare_amend_pegged_order__ + +print(f"Amendment prepared for order ID: {orderID}") + +# __sign_tx_pegged_amend: +# Sign the prepared pegged order transaction for amendment +# Note: Setting propagate to true will also submit to a Vega node +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +# :sign_tx_pegged_amend__ + +print("Signed pegged order amendment and sent to Vega") + +# Wait for amendment to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +order_id_request = vac.api.trading.OrderByIDRequest(order_id=orderID) +response = data_client.OrderByID(order_id_request) +orderID = response.order.id +orderPrice = response.order.status +orderSize = response.order.size +orderTif = helpers.enum_to_str( + vac.vega.Order.TimeInForce, response.order.time_in_force +) +orderStatus = helpers.enum_to_str( + vac.vega.Order.Status, response.order.status +) +orderVersion = response.order.version +orderReason = response.order.reason + +print("Amended pegged order:") +print(f"ID: {orderID}, Status: {orderStatus}, " + f"Size(Old): 50, Size(New): {orderSize}, " + f"TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): {orderTif}, " + f"Version(Old): {createVersion}, Version(new): {orderVersion}") + +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") +else: + print(f"Pegged at:\n{response.order.pegged_order}") + +# Completed. diff --git a/grpc/examples/python/submit-liquidity-provision-order.py b/grpc/examples/python/submit-liquidity-provision-order.py new file mode 100644 index 00000000..b30f30e9 --- /dev/null +++ b/grpc/examples/python/submit-liquidity-provision-order.py @@ -0,0 +1,208 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (gRPC) + +Apps/Libraries: +- Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import base64 +import helpers +import time +import requests + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# __import_client: +import vegaapiclient as vac + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_grpc = helpers.get_from_env("NODE_URL_GRPC") + +# Vega gRPC clients for reading/writing data +data_client = vac.VegaTradingDataClient(node_url_grpc) +trading_client = vac.VegaTradingClient(node_url_grpc) +# :import_client__ + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +markets = data_client.Markets(vac.api.trading.MarketsRequest()).markets +marketID = markets[0].id +# :get_market__ + +assert marketID != "" +marketName = markets[0].tradable_instrument.instrument.name +print(f"Market found: {marketID} {marketName}") + +############################################################################### +# L I S T L I Q U I D I T Y P R O V I S I O N S # +############################################################################### + +# __get_liquidity_provisions: +# Request liquidity provisions for the market + +# specify party ID below if needed, otherwise all liquidity +# provisions for the market get returned +partyID = "" +liquidityProvisions = data_client.LiquidityProvisions( + vac.api.trading.LiquidityProvisionsRequest( + party=partyID, + market=marketID + ) +) + +print("Liquidity provisions:\n{}".format(liquidityProvisions)) +# :get_liquidity_provisions__ + +############################################################################### +# S U B M I T L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# Note: commitment_amount is an integer. For example 123456 is a price of +# 1.23456, for a market configured to have a precision of 5 decimal places. + +# __prepare_liquidity_order: +# Prepare a liquidity commitment transaction message +order = vac.api.trading.PrepareLiquidityProvisionRequest( + submission=vac.commands.v1.commands.LiquidityProvisionSubmission( + market_id=marketID, + commitment_amount=100, + fee="0.01", + reference="my-lp-reference", + buys=[ + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=1, + offset=-1 + ), + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=2, + offset=-2 + ) + ], + sells=[ + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=1, + offset=1 + ), + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=2, + offset=2 + ), + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=5, + offset=3 + ) + ] + ) +) +prepared_order = trading_client.PrepareLiquidityProvision(order) +# :prepare_liquidity_order__ + +############################################################################### +# A M E N D L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# __amend_liquidity_order: +# Prepare a liquidity commitment order message (it will now serve as an +# amendment request): modify fields to be amended +order = vac.api.trading.PrepareLiquidityProvisionRequest( + submission=vac.commands.v1.commands.LiquidityProvisionSubmission( + market_id=marketID, + commitment_amount=500, + fee="0.005", + reference="my-lp-reference", + buys=[ + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=1, + offset=-1 + ) + ], + sells=[ + vac.vega.LiquidityOrder( + reference=vac.vega.PEGGED_REFERENCE_MID, + proportion=1, + offset=1 + ) + ] + ) +) +prepared_order = trading_client.PrepareLiquidityProvision(order) +# :amend_liquidity_order__ + +print(f"Prepared liquidity commitment (amendment) for market: {marketID}") + +# Sign the prepared transaction +# Note: Setting propagate to true will submit to a Vega node +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) + +print("Signed order and sent to Vega") + +time.sleep(10) + +############################################################################### +# C A N C E L L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# __cancel_liquidity_order: +# Prepare a liquidity commitment order message (it will now serve as a +# cancellation request): set commitmentAmount to 0, note that transaction +# may get rejected if removing previously supplied liquidity +# will result in insufficient liquidity for the market +order = vac.api.trading.PrepareLiquidityProvisionRequest( + submission=vac.commands.v1.commands.LiquidityProvisionSubmission( + market_id=marketID, + commitment_amount=0, + reference="my-lp-reference", + ) +) +prepared_order = trading_client.PrepareLiquidityProvision(order) +# :cancel_liquidity_order__ + +print(f"Prepared liquidity commitment (cancellation) for market: {marketID}") + +# Sign the prepared transaction +# Note: Setting propagate to true will submit to a Vega node +blob_base64 = base64.b64encode(prepared_order.blob).decode("ascii") +req = {"tx": blob_base64, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) + +print("Signed order and sent to Vega") + + +# Completed. diff --git a/grpc/examples/python/wallet-with-Vega-API-client.py b/grpc/examples/python/wallet-with-Vega-API-client.py new file mode 100644 index 00000000..c1bb43a5 --- /dev/null +++ b/grpc/examples/python/wallet-with-Vega-API-client.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) + +Apps/Libraries: +- REST: Vega-API-client (https://pypi.org/project/Vega-API-client/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import base64 +import json +import os + +# __import_client: +import vegaapiclient as vac + +# :import_client__ + +import helpers + +wallet_name = helpers.random_string() +wallet_passphrase = helpers.random_string() + +wallet_server_url = os.getenv("WALLETSERVER_URL") +if not helpers.check_url(wallet_server_url): + print("Error: Invalid or missing WALLETSERVER_URL environment variable.") + exit(1) + +# Help guide users against including api version suffix on url +wallet_server_url = helpers.check_wallet_url(wallet_server_url) + +print(f"Creating a new wallet on {wallet_server_url}:") +print(f"- name: {wallet_name}") +print(f"- passphrase: {wallet_passphrase}") + +# __create_wallet: +# Create a new wallet +wallet_client = vac.WalletClient(wallet_server_url) +response = wallet_client.create(wallet_name, wallet_passphrase) +helpers.check_response(response) +# :create_wallet__ + + +# The example below uses the credentials we just created +# and in practice you don't need to log in immediately after +# creating a new wallet, as the response already contains the +# token that you need to authenticate with future requests. + + +# __login_wallet: +# Log in to an existing wallet +response = wallet_client.login(wallet_name, wallet_passphrase) +helpers.check_response(response) +# :login_wallet__ + + +# __generate_keypair: +# Generate a new keypair +response = wallet_client.generatekey(wallet_passphrase, []) +helpers.check_response(response) +# Print key information. Note that the private key is *not* returned. +keypair = response.json()["key"] +print("Generated new key pair:") +print(json.dumps(keypair, indent=2, sort_keys=True)) +# :generate_keypair__ + + +# __get_keys: +# Request all key pairs +response = wallet_client.listkeys() +helpers.check_response(response) +keys = response.json()["keys"] +for key in keys: + print("List key pairs:") + print(json.dumps(key, indent=2, sort_keys=True)) +# :get_keys__ + + +# __get_key: +# Request a single key pair +response = wallet_client.getkey(keys[0]["pub"]) +helpers.check_response(response) +key = response.json()["key"] +print("Get a single key pair:") +print(json.dumps(key, indent=2, sort_keys=True)) +# :get_key__ + + +# __sign_tx: +# Sign a transaction +blob = b"data returned from a Vega node 'Prepare' call" +tx = base64.b64encode(blob).decode("ascii") +response = wallet_client.signtx(tx, keypair["pub"], propagate=False) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +print("Signed transaction:") +print(json.dumps(signedTx, indent=2, sort_keys=True)) +# :sign_tx__ + + +# __logout_wallet: +# Log out of a wallet +response = wallet_client.logout() +helpers.check_response(response) +# :logout_wallet__ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..45111c41 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +googleapis-common-protos==1.52.0 +grpcio==1.35.0 +requests==2.25.1 +Vega-API-client==0.38.1 +websocket-client==0.57.0 diff --git a/rest/examples/python/Makefile b/rest/examples/python/Makefile index 9c78225d..5fe25d0c 100644 --- a/rest/examples/python/Makefile +++ b/rest/examples/python/Makefile @@ -4,4 +4,4 @@ default: @pipenv --bare sync @pipenv --bare clean - @env PYTHONPATH=../../../grpc/examples/python:. pipenv run python3 submit-order.py --ci + @env PYTHONPATH=../../../rest/examples/python:. pipenv run python3 submit-order.py --ci diff --git a/rest/examples/python/get-accounts.py b/rest/examples/python/get-accounts.py new file mode 100755 index 00000000..f887cb45 --- /dev/null +++ b/rest/examples/python/get-accounts.py @@ -0,0 +1,88 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) + +Responses: +- response-examples.txt +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import pubkey + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# M A R K E T A C C O U N T S # +############################################################################### + +# Request a list of markets and select the first one +url = f"{node_url_rest}/markets" +response = requests.get(url) +helpers.check_response(response) +marketID = response.json()["markets"][0]["id"] + +assert marketID != "" +print(f"Market found: {marketID}") + +# __get_accounts_by_market: +# Request a list of accounts for a market on a Vega network +url = f"{node_url_rest}/markets/{marketID}/accounts" +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("Market accounts:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_accounts_by_market__ + +############################################################################### +# P A R T Y A C C O U N T S # +############################################################################### + +# __get_accounts_by_party: +# Request a list of accounts for a party (pubkey) on a Vega network +url = f"{node_url_rest}/parties/{pubkey}/accounts" +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("Party accounts:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_accounts_by_party__ + +############################################################################### +# P A R T Y P O S I T I O N S # +############################################################################### + +# __get_positions_by_party: +# Request a list of positions for a party (pubkey) on a Vega network +url = f"{node_url_rest}/parties/{pubkey}/positions" +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("Party positions:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_positions_by_party__ diff --git a/rest/examples/python/get-assets.py b/rest/examples/python/get-assets.py new file mode 100644 index 00000000..34a700ef --- /dev/null +++ b/rest/examples/python/get-assets.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import json +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_assets: +# Request a list of assets available on a Vega network +url = "{base}/assets".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +print("Assets:\n{}".format( + json.dumps(response.json(), indent=2, sort_keys=True))) +# :get_assets__ + +# Find asset with name DAI +found_asset_id = "UNKNOWN" +assets = response.json()["assets"] +for asset in assets: + if asset["details"]["symbol"] == "tDAI": + print() + print("Found an asset with symbol tDAI:") + found_asset_id = asset["id"] + print(found_asset_id) + print() + break + +if found_asset_id == "UNKNOWN": + print("tDAI asset not found on specified Vega network, " + + "please propose and create the tDAI asset") + +assert found_asset_id != "UNKNOWN" +print() + +# __get_asset: +# Request a single asset by identifier on a Vega network +url = "{base}/assets/{id}".format(base=node_url_rest, id=found_asset_id) +response = requests.get(url) +helpers.check_response(response) +print("Asset by ID:\n{}".format( + json.dumps(response.json(), indent=2, sort_keys=True))) +# :get_asset__ + +# Completed. diff --git a/rest/examples/python/get-fees-margins-estimate.py b/rest/examples/python/get-fees-margins-estimate.py new file mode 100644 index 00000000..7f6298b0 --- /dev/null +++ b/rest/examples/python/get-fees-margins-estimate.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import pubkey + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +url = f"{node_url_rest}/markets" +response = requests.get(url) +helpers.check_response(response) +marketID = response.json()["markets"][0]["id"] +# :get_market__ + +assert marketID != "" +print(f"Market found: {marketID}") + +############################################################################### +# F E E E S T I M A T I O N # +############################################################################### + +# __get_fees_estimate: +# Request to estimate trading fees on a Vega network +req = { + "order": { + "marketId": marketID, + "partyId": pubkey, + "price": "100000", + "size": "100", + "side": "SIDE_BUY", + "timeInForce": "TIME_IN_FORCE_GTC", + "type": "TYPE_LIMIT", + } +} +print(json.dumps(req, indent=2, sort_keys=True)) +url = f"{node_url_rest}/orders/fee/estimate" +response = requests.post(url, json=req) +helpers.check_response(response) +estimatedFees = response.json() +print("FeeEstimates:\n{}".format( + json.dumps(estimatedFees, indent=2, sort_keys=True))) +# :get_fees_estimate__ + +############################################################################### +# M A R G I N E S T I M A T I O N # +############################################################################### + +# __get_margins_estimate: +# Request to estimate trading margin on a Vega network +req = { + "order": { + "marketId": marketID, + "partyId": pubkey, + "price": "600000", + "size": "10", + "side": "SIDE_BUY", + "timeInForce": "TIME_IN_FORCE_GTC", + "type": "TYPE_LIMIT", + } +} +print(json.dumps(req, indent=2, sort_keys=True)) +url = f"{node_url_rest}/orders/margins/estimate" +response = requests.post(url, json=req) +helpers.check_response(response) +estimatedMargin = response.json() +print("MarginsEstimate:\n{}".format( + json.dumps(estimatedMargin, indent=2, sort_keys=True))) +# :get_margins_estimate__ diff --git a/rest/examples/python/get-markets-and-marketdata.py b/rest/examples/python/get-markets-and-marketdata.py new file mode 100644 index 00000000..e4ed92cb --- /dev/null +++ b/rest/examples/python/get-markets-and-marketdata.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_markets: +# Request a list of markets available on a Vega network +url = "{base}/markets".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("Markets:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_markets__ + +market_id = response_json["markets"][0]["id"] +assert market_id != "" + +# __get_market_data: +# Request the market data for a market on a Vega network +url = "{base}/markets-data/{marketId}".format( + base=node_url_rest, marketId=market_id +) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("MarketData:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_market_data__ diff --git a/rest/examples/python/get-network-parameters.py b/rest/examples/python/get-network-parameters.py new file mode 100644 index 00000000..a1a638ac --- /dev/null +++ b/rest/examples/python/get-network-parameters.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import json +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# N E T W O R K P A R A M E T E R S # +############################################################################### + +# __get_network_params: +# Request a list of network parameters configured on a Vega network +url = "{base}/network/parameters".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +print("Network Parameters:\n{}".format( + json.dumps(response.json(), indent=2, sort_keys=True))) +# :get_network_params__ diff --git a/rest/examples/python/get-order-by-reference.py b/rest/examples/python/get-order-by-reference.py new file mode 100644 index 00000000..dce68fe4 --- /dev/null +++ b/rest/examples/python/get-order-by-reference.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_order_by_ref: +# Request an order by reference on a Vega network +# Note: This is an example and order reference will be provided in the response +# from a prepareSubmitOrder request in the field named `submitID` or similar. +reference = "4617844f-6fab-4cf6-8852-e29dbd96e5f1" +url = "{base}/orders/{ref}".format(base=node_url_rest, ref=reference) +response = requests.get(url) +helpers.check_response(response) +print("OrderByReference:\n{}".format( + json.dumps(response.json(), indent=2, sort_keys=True))) +# :get_order_by_ref__ diff --git a/rest/examples/python/get-orders-and-trades-for-market.py b/rest/examples/python/get-orders-and-trades-for-market.py new file mode 100644 index 00000000..41fbcc0c --- /dev/null +++ b/rest/examples/python/get-orders-and-trades-for-market.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +url = "{base}/markets".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +responseJson = response.json() +marketID = responseJson["markets"][0]["id"] +assert marketID != "" + +# __get_orders_for_market: +# Request a list of orders by market on a Vega network +url = "{base}/markets/{marketID}/orders".format( + base=node_url_rest, marketID=marketID +) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("OrdersByMarket:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_orders_for_market__ + +# __get_trades_for_market: +# Request a list of trades by market on a Vega network +url = "{base}/markets/{marketID}/trades".format( + base=node_url_rest, marketID=marketID +) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("TradesByMarket:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_trades_for_market__ diff --git a/rest/examples/python/get-orders-and-trades-for-party.py b/rest/examples/python/get-orders-and-trades-for-party.py new file mode 100644 index 00000000..3f0f3641 --- /dev/null +++ b/rest/examples/python/get-orders-and-trades-for-party.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey +print(token) + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_orders_for_party: +# Request a list of orders by party (pubKey) +url = "{base}/parties/{party}/orders".format(base=node_url_rest, party=pubkey) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("OrdersByParty:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_orders_for_party__ + +# __get_trades_for_party: +# Request a list of trades by party (pubKey) +url = "{base}/parties/{party}/trades".format(base=node_url_rest, party=pubkey) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("TradesByParty:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_trades_for_party__ diff --git a/rest/examples/python/get-parties.py b/rest/examples/python/get-parties.py new file mode 100755 index 00000000..97768b94 --- /dev/null +++ b/rest/examples/python/get-parties.py @@ -0,0 +1,56 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) + +Responses: +- response-examples.txt +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_parties: +# Request a list of parties trading on a Vega network +url = "{base}/parties".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("Parties:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_parties__ + +assert len(response_json["parties"]) > 0 +pubkey = response_json["parties"][0]["id"] + +# __get_party_by_id: +# Request a party by their identifier (this is their public key) +url = "{base}/parties/{partyID}".format(base=node_url_rest, partyID=pubkey) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() +print("PartyById:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_party_by_id__ diff --git a/rest/examples/python/get-proposals.py b/rest/examples/python/get-proposals.py new file mode 100644 index 00000000..a39a21ba --- /dev/null +++ b/rest/examples/python/get-proposals.py @@ -0,0 +1,82 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) +- Vega wallet (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Vega wallet interaction helper, please see login.py for more detail +from login import token, pubkey +print(token) + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# L I S T P R O P O S A L S # +############################################################################### + +# There are two types of REST request for proposals on Vega: +# 1 - MARKET proposals (/governance/market/proposals) +# 2 - ASSET proposals (/governance/asset/proposals) +# Note: Future users will be able to call an endpoint to retrieve ALL proposals + +# __get_proposals: +# Request a list of proposals on a Vega network +response = requests.get(node_url_rest + "/governance/market/proposals") +helpers.check_response(response) +proposals = response.json() +print("Proposals:\n{}".format(json.dumps(proposals, indent=2, sort_keys=True))) +# :get_proposals__ + +proposalID = proposals["data"][0]["proposal"]["id"] +assert proposalID != "" +print(f"Proposal found: {proposalID}") + +############################################################################### +# P R O P O S A L D E T A I L S # +############################################################################### + +# __get_proposal_detail: +# Request results of a specific proposal on a Vega network +response = requests.get(node_url_rest + "/governance/proposal/" + proposalID) +helpers.check_response(response) +response_json = response.json() +print("Proposal:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_proposal_detail__ + +############################################################################### +# P A R T Y P R O P O S A L S # +############################################################################### + +# __get_proposals_by_party: +# Request results of a specific proposal on a Vega network +response = requests.get(node_url_rest + "/parties/" + pubkey + "/proposals") +helpers.check_response(response) +response_json = response.json() +print("Party proposals:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_proposals_by_party__ diff --git a/rest/examples/python/get-statistics.py b/rest/examples/python/get-statistics.py new file mode 100644 index 00000000..bf902080 --- /dev/null +++ b/rest/examples/python/get-statistics.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_statistics: +# Request the statistics for a node on Vega +url = "{base_url}/statistics".format(base_url=node_url_rest) +response = requests.get(url) +helpers.check_response(response) +print("Statistics:\n{}".format(response.json())) +# :get_statistics__ diff --git a/rest/examples/python/get-time.py b/rest/examples/python/get-time.py new file mode 100755 index 00000000..8cbae86c --- /dev/null +++ b/rest/examples/python/get-time.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_time: +# Request the latest timestamp in nanoseconds since epoch from the Vega network +url = "{base}/time".format(base=node_url_rest) +response = requests.get(url) +helpers.check_response(response) + +# The "timestamp" field contains the resulting data we need. +vega_time = response.json()["timestamp"] +print("Vega time:\n{}".format(vega_time)) +# :get_time__ diff --git a/rest/examples/python/get-trades-for-order.py b/rest/examples/python/get-trades-for-order.py new file mode 100644 index 00000000..8dc70e93 --- /dev/null +++ b/rest/examples/python/get-trades-for-order.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import json +import requests +import helpers + +# Load REST Vega Node URL, this is set using 'source examples-config' +# located in the root folder of the api repository +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +# __get_trades_for_order: +# Request a list of trades for a specific order on a Vega network +orderID = "V0000929211-0046318720" +url = "{base}/orders/{orderID}/trades".format( + base=node_url_rest, orderID=orderID +) +response = requests.get(url) +helpers.check_response(response) +responseJson = response.json() +print("TradesByOrderID:\n{}".format( + json.dumps(responseJson, indent=2, sort_keys=True) +)) +# :get_trades_for_order__ diff --git a/rest/examples/python/helpers.py b/rest/examples/python/helpers.py new file mode 100644 index 00000000..5a78f477 --- /dev/null +++ b/rest/examples/python/helpers.py @@ -0,0 +1,83 @@ +import random +import os +import requests +import string +from typing import Any + + +def check_response(r: requests.Response) -> None: + """ + Raise a helpful exception if the HTTP response was not 200. + """ + if r.status_code != 200: + raise Exception(f"{r.url} returned HTTP {r.status_code} {r.text}") + + +def check_var(val: str) -> bool: + """ + Return true if the value is ok. + """ + if val is None or val == "": + return False + if invalid(val): + return False + return True + + +def check_url(url: str) -> bool: + """ + Return true if the URL is ok. + """ + if not check_var(url): + return False + if not any(url.startswith(prefix) for prefix in ["http://", "https://"]): + return False + return True + + +def get_from_env(var_name: str) -> str: + """ + Get a value from an environment variable. Used in CI for testing. + """ + val = os.getenv(var_name, "") + if val == "": + print(f"Error: Missing environment variable {var_name}.") + exit(1) + + return val + + +def invalid(val: str) -> bool: + """ + Return true if none of the invalid strings are found in the value. + """ + bzzt = [">>", "e.g.", "example"] + return any(x in val for x in bzzt) + + +def random_string(length: int = 20) -> str: + """ + Generate a random string, made of letters and digits. + """ + choices = string.ascii_letters + string.digits + return "".join(random.choice(choices) for i in range(length)) + + +def fix_walletserver_url(url: str) -> str: + """ + Help guide users against including api version suffix in wallet server URL. + """ + for suffix in ["/api/v1/", "/api/v1", "/api/", "/api", "/"]: + if not url.endswith(suffix): + continue + print( + f'There\'s no need to add "{suffix}" to the wallet server URL. ' + "Removing it and continuing..." + ) + url = url[: -len(suffix)] + + return url + + +def enum_to_str(e: Any, val: int) -> str: + return e.keys()[e.values().index(val)] diff --git a/rest/examples/python/login.py b/rest/examples/python/login.py new file mode 100644 index 00000000..e7446364 --- /dev/null +++ b/rest/examples/python/login.py @@ -0,0 +1,71 @@ +import requests +import os.path +import json +import sys +import helpers + +ci_args = "--ci" +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") + + +def load_token(): + if ci_args in sys.argv: + return perform_login() + # login will call exit with appropriate code + if not os.path.isfile("token.temp"): + print('Error: No token file found: try running "python3 login.py"') + exit(1) + with open("token.temp", "r") as token_file: + return json.load(token_file)["token"] + + +def get_pubkey(token): + auth_headers = {"Authorization": "Bearer " + token} + response = requests.get(wallet_server_url + "/api/v1/keys", + headers=auth_headers) + if response.status_code != 200: + print("Error listing keys: " + response.text) + exit(1) + keys = response.json()["keys"] + if len(keys) < 1: + print("Error: No keys found, use Vega Console" + + " or Vega Wallet CLI to create one") + exit(1) + return keys[0]["pub"], auth_headers + + +def perform_login(): + import getpass + wallet_name = os.getenv("WALLET_NAME") + wallet_passphrase = os.getenv("WALLET_PASSPHRASE") + valid_user = helpers.check_var(wallet_name) + valid_pass = helpers.check_var(wallet_passphrase) + if ci_args in sys.argv and not valid_user: + print("Error: Missing environment variable WALLET_NAME") + exit(1) + if ci_args in sys.argv and not valid_pass: + print("Error: Missing environment variable WALLET_PASSPHRASE") + exit(1) + if not valid_user or not valid_pass: + wallet_name = input("Enter Vega wallet username: ") + wallet_passphrase = getpass.getpass("Vega wallet passphrase: ") + req = {"wallet": wallet_name, "passphrase": wallet_passphrase} + response = requests.post(wallet_server_url + + "/api/v1/auth/token", json=req) + if response.status_code != 200: + print("Error logging in: " + response.text) + exit(1) + if ci_args not in sys.argv: + with open("token.temp", "w") as token_file: + json.dump(response.json(), token_file) + print('Token saved to "token.temp", done.') + return response.json()["token"] + + +if __name__ == "__main__": + perform_login() + exit(0) + + +token = load_token() +pubkey, auth_headers = get_pubkey(token) diff --git a/rest/examples/python/propose-vote-enact-market.py b/rest/examples/python/propose-vote-enact-market.py new file mode 100644 index 00000000..d9c02ec5 --- /dev/null +++ b/rest/examples/python/propose-vote-enact-market.py @@ -0,0 +1,405 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) +- Vega wallet (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import time +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D A S S E T S # +############################################################################### + +# __get_assets: +# Request a list of assets available on a Vega network +url = f"{node_url_rest}/assets" +response = requests.get(url) +helpers.check_response(response) +# :get_assets__ + +# Debugging +# print("Assets:\n{}".format( +# json.dumps(response.json(), indent=2, sort_keys=True))) + +# __find_asset: +# Find settlement asset with name tDAI +found_asset_id = "UNKNOWN" +print(response) +assets = response.json()["assets"] +for asset in assets: + if asset["symbol"] == "tDAI": + print("Found an asset with symbol tDAI") + print(asset) + found_asset_id = asset["id"] + break +# :find_asset__ + +if found_asset_id == "UNKNOWN": + print( + "tDAI asset not found on specified Vega network, please propose and " + "create this asset first" + ) + exit(1) + +############################################################################### +# G O V E R N A N C E T O K E N C H E C K # +############################################################################### + +# Get the identifier of the governance asset on the Vega network +vote_asset_id = "UNKNOWN" +for asset in assets: + if asset["symbol"] == "tVOTE": + vote_asset_id = asset["id"] + break + +if vote_asset_id == "UNKNOWN": + print( + "tVOTE asset not found on specified Vega network, please symbol name " + "check and try again" + ) + exit(1) + +# Request accounts for party and check governance asset balance +url = f"{node_url_rest}/parties/{pubkey}/accounts" +response = requests.get(url) +helpers.check_response(response) + +# Debugging +# print("Accounts:\n{}".format( +# json.dumps(response.json(), indent=2, sort_keys=True))) + +voting_balance = 0 +accounts = response.json()["accounts"] +for account in accounts: + if account["asset"] == vote_asset_id: + print("Found governance asset account") + print(account) + voting_balance = account["balance"] + break + +if voting_balance == 0: + print(f"Please deposit tVOTE asset to public key {pubkey} and try again") + exit(1) + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_time: +# Request the current blockchain time, and convert to time in seconds +response = requests.get(f"{node_url_rest}/time") +helpers.check_response(response) +blockchain_time = int(response.json()["timestamp"]) +blockchain_time_seconds = int(blockchain_time / 1e9) # Seconds precision +# :get_time__ + +assert blockchain_time > 0 +assert blockchain_time_seconds > 0 +print( + f"Blockchain time: {blockchain_time} ({blockchain_time_seconds} seconds " + "past epoch)" +) + +############################################################################### +# P R O P O S E M A R K E T # +############################################################################### + +# STEP 1 - Propose a BTC/DAI futures market + +# Further documentation on creating markets: +# https://docs.testnet.vega.xyz/docs/api-howtos/create-market/ + +# __prepare_propose_market: +# Prepare a market proposal for a new market +market = { + "partyId": pubkey, + "proposal": { + # Set closing timestamp to a valid time offset from the current Vega + # blockchain time + "closingTimestamp": blockchain_time_seconds + 360, + # Set enactment timestamp to a valid time offset from the current Vega + # blockchain time + "enactmentTimestamp": blockchain_time_seconds + 480, + # Set validation timestamp to a valid time offset from the current Vega + # blockchain time + "validationTimestamp": blockchain_time_seconds + 1, + # Note: the timestamps above are specified in seconds, and must meet + # minimums required by network + "newMarket": { + "changes": { + "instrument": { + "name": "BTC/DAI", + "code": "CRYPTO:BTCDAI/JUN21", + "future": { + "maturity": "2021-06-30T23:59:59Z", + # Settlement asset identifier (found above) + "settlementAsset": found_asset_id, + "quoteName": "DAI", + "oracleSpec": { + "pubKeys": ["0x0000"], + "filters": [ + { + "key": { + "name": "price.DAI.value", + "type": "TYPE_STRING", + }, + "conditions": [ + { + "operator": "OPERATOR_EQUALS", + "value": "5797800153", + }, + ], + }, + ], + }, + "oracleSpecBinding": { + "settlementPriceProperty": "price.DAI.value" + }, + }, + }, + "decimalPlaces": "5", + "metadata": [ + "base:BTC", + "quote:DAI", + ], + "priceMonitoringParameters": { + "triggers": [ + { + "horizon": "43200", + "probability": 0.9999999, + "auctionExtension": "300", + } + ], + "updateFrequency": "120", + }, + "liquidityMonitoringParameters": { + "targetStakeParameters": { + "timeWindow": 3600, + "scalingFactor": 10, + }, + "triggeringRatio": 0, + "auctionExtension": 0, + }, + "logNormal": { + "riskAversionParameter": 0.01, + "tau": 1.90128526884173e-06, + "params": {"mu": 0, "r": 0.016, "sigma": 0.05}, + }, + "continuous": {"tickSize": "0.01"}, + }, + "liquidityCommitment": { + "commitmentAmount": 1, + "fee": "0.01", + "sells": [ + { + "reference": "PEGGED_REFERENCE_BEST_ASK", + "proportion": 10, + "offset": 2000, + }, + { + "reference": "PEGGED_REFERENCE_BEST_ASK", + "proportion": 10, + "offset": 1000, + }, + ], + "buys": [ + { + "reference": "PEGGED_REFERENCE_BEST_BID", + "proportion": 10, + "offset": -1000, + }, + { + "reference": "PEGGED_REFERENCE_BEST_BID", + "proportion": 10, + "offset": -2000, + }, + ], + "reference": "", + }, + }, + }, +} + +url = f"{node_url_rest}/governance/prepare/proposal" +response = requests.post(url, json=market) +helpers.check_response(response) +prepared_proposal = response.json() +# :prepare_propose_market__ + +proposal_ref = prepared_proposal["pendingProposal"]["reference"] +print(f"Prepared proposal, ref: {proposal_ref}") +assert proposal_ref != "" + +# __sign_tx_proposal: +# Sign the prepared proposal transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_proposal["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_proposal__ + +print("Signed market proposal and sent to Vega") + +# Debugging +# print("Signed transaction:\n", response.json(), "\n") + +# Wait for proposal to be included in a block and to be accepted by Vega +# network +print("Waiting for blockchain...", end="", flush=True) +proposal_id = "" +done = False +while not done: + time.sleep(0.5) + print(".", end="", flush=True) + my_proposals = requests.get( + node_url_rest + "/parties/" + pubkey + "/proposals" + ) + if my_proposals.status_code != 200: + continue + + for n in my_proposals.json()["data"]: + if n["proposal"]["reference"] == proposal_ref: + proposal_id = n["proposal"]["id"] + print() + print("Your proposal has been accepted by the network") + print(n) + done = True + break + +assert proposal_id != "" + +############################################################################### +# V O T E O N M A R K E T # +############################################################################### + +# STEP 2 - Let's vote on the market proposal + +# IMPORTANT: When voting for a proposal on the Vega Testnet, typically a single +# YES vote from the proposer will not be enough to vote the market into +# existence. This is because of the network minimum threshold for voting on +# proposals, this threshold for market proposals this is currently a 66% +# majority vote either YES or NO. +# A proposer should enlist the help/YES votes from other community members, +# ideally on the Community forums (https://community.vega.xyz/c/testnet) or +# Discord (https://vega.xyz/discord) + +# Further documentation on proposal voting and review here: +# https://docs.testnet.vega.xyz/docs/api-howtos/proposals/ + +# __prepare_vote: +# Prepare a vote for the proposal +vote = { + "vote": { + "partyId": pubkey, + "value": "VALUE_YES", # Can be either VALUE_YES or VALUE_NO + "proposalId": proposal_id, + } +} + +url = f"{node_url_rest}/governance/prepare/vote" +response = requests.post(url, json=vote) +helpers.check_response(response) +prepared_vote = response.json() +# :prepare_vote__ + +# Debugging +# print("Prepared vote:\n", prepared_vote, "\n") + +# __sign_tx_vote: +# Sign the prepared vote transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_vote["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_vote__ + +print("Signed vote on proposal and sent to Vega") + +# Debugging +# print("Signed transaction:\n", response.json(), "\n") + +print("Waiting for vote on proposal to succeed or fail...", end="", flush=True) +done = False +while not done: + time.sleep(0.5) + my_proposals = requests.get( + node_url_rest + "/parties/" + pubkey + "/proposals" + ) + if my_proposals.status_code != 200: + continue + + for n in my_proposals.json()["data"]: + if n["proposal"]["reference"] == proposal_ref: + if n["proposal"]["state"] != "STATE_OPEN": + print(n["proposal"]["state"]) + if n["proposal"]["state"] == "STATE_ENACTED": + done = True + break + elif n["proposal"]["state"] == "STATE_PASSED": + print("proposal vote has succeeded, waiting for enactment") + else: + print(n) + exit(1) + +############################################################################### +# W A I T F O R M A R K E T # +############################################################################### + +# STEP 3 - Wait for market to be enacted + +# IMPORTANT: When voting for a proposal on the Vega Testnet, typically a single +# YES vote from the proposer will not be enough to vote the market into +# existence. As described above in STEP 2, a market will need community voting +# support to be passed and then enacted. + +# __wait_for_market: +print("Waiting for proposal to be enacted or failed...", end="", flush=True) +done = False +while not done: + time.sleep(0.5) + print(".", end="", flush=True) + markets = requests.get(node_url_rest + "/markets") + if markets.status_code != 200: + continue + + for n in markets.json()["markets"]: + if n["id"] == proposal_id: + print() + print(n) + done = True + break +# :wait_for_market__ + +# Completed. diff --git a/rest/examples/python/propose-vote-enact-netparams.py b/rest/examples/python/propose-vote-enact-netparams.py new file mode 100644 index 00000000..7bf699c4 --- /dev/null +++ b/rest/examples/python/propose-vote-enact-netparams.py @@ -0,0 +1,268 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega node (REST) +- Vega wallet (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import requests +import time +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D A S S E T S # +############################################################################### + +# __get_assets: +# Request a list of assets available on a Vega network +url = f"{node_url_rest}/assets" +response = requests.get(url) +helpers.check_response(response) +# :get_assets__ + +# Debugging +# print("Assets:\n{}".format( +# json.dumps(response.json(), indent=2, sort_keys=True))) + +# __find_asset: +# Find settlement asset with name tDAI +found_asset_id = "UNKNOWN" +print(response) +assets = response.json()["assets"] + +############################################################################### +# G O V E R N A N C E T O K E N C H E C K # +############################################################################### + +# Get the identifier of the governance asset on the Vega network +vote_asset_id = "UNKNOWN" +for asset in assets: + if asset["symbol"] == "tVOTE": + vote_asset_id = asset["id"] + break + +if vote_asset_id == "UNKNOWN": + print("tVOTE asset not found on specified Vega network," + + " please symbol name check and try again") + exit(1) + +# Request accounts for party and check governance asset balance +url = f"{node_url_rest}/parties/{pubkey}/accounts" +response = requests.get(url) +helpers.check_response(response) + +# Debugging +# print("Accounts:\n{}".format( +# json.dumps(response.json(), indent=2, sort_keys=True))) + +voting_balance = 0 +accounts = response.json()["accounts"] +for account in accounts: + if account["asset"] == vote_asset_id: + print("Found governance asset account") + print(account) + voting_balance = account["balance"] + break + +if voting_balance == 0: + print(f"Please deposit tVOTE asset to public key {pubkey} and try again") + exit(1) + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_time: +# Request the current blockchain time, and convert to time in seconds +response = requests.get(f"{node_url_rest}/time") +helpers.check_response(response) +blockchain_time = int(response.json()["timestamp"]) +blockchain_time_seconds = int(blockchain_time / 1e9) # Seconds precision +# :get_time__ + +assert blockchain_time > 0 +assert blockchain_time_seconds > 0 +print(f"Blockchain time: {blockchain_time} " + + f"({blockchain_time_seconds} seconds past epoch)") + +############################################################################### +# U P D A T E N E T W O R K P A R A M E T E R # +############################################################################### + +# Step 1 propose a network parameter update + +parameter = "market.liquidity.targetstake.triggering.ratio" +value = "0.7" + +# __prepare_propose_updateNetworkParameter: +# Prepare a proposal for a network parameter update +market = { + "partyId": pubkey, + "proposal": { + # Set validation timestamp to a valid time offset from the current + # Vega blockchain time + "validationTimestamp": blockchain_time_seconds + 1, + # Set closing timestamp to a valid time offset from the current Vega + # blockchain time + "closingTimestamp": blockchain_time_seconds + 3600 + 60, + # Set enactment timestamp to a valid time offset from the current Vega + # blockchain time + "enactmentTimestamp": blockchain_time_seconds + 3600 + 120, + # Note: the timestamps above are specified in seconds, and must meet + # minimums required by network. This is the main part: "key" is any + # network parameter and "value" is its value. As an example we vote to + # change the parameter market.liquidity.targetstake.triggering.ratio. + "updateNetworkParameter": { + "changes": { + "key": "market.liquidity.targetstake.triggering.ratio", + "value": "0.7", + } + }, + }, +} + +url = f"{node_url_rest}/governance/prepare/proposal" +response = requests.post(url, json=market) +helpers.check_response(response) +prepared_proposal = response.json() +# :prepare_propose_market__ + +proposal_ref = prepared_proposal["pendingProposal"]["reference"] +print(f"Prepared proposal, ref: {proposal_ref}") +assert proposal_ref != "" + +# __sign_tx_proposal: +# Sign the prepared proposal transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_proposal["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_proposal__ + +print("Signed market proposal and sent to Vega") + +# Debugging +# print("Signed transaction:\n", response.json(), "\n") + +# Wait for proposal to be included in a block and be accepted by Vega network +print("Waiting for blockchain...", end="", flush=True) +proposal_id = "" +done = False +while not done: + time.sleep(0.5) + print(".", end="", flush=True) + my_proposals = requests.get(node_url_rest + "/parties/" + + pubkey + "/proposals") + if my_proposals.status_code != 200: + continue + + for n in my_proposals.json()["data"]: + if n["proposal"]["reference"] == proposal_ref: + proposal_id = n["proposal"]["id"] + print() + print("Your proposal has been accepted by the network") + print(n) + done = True + break + +assert proposal_id != "" + +############################################################################### +# V O T E O N P A R A M E T E R # +############################################################################### + +# STEP 2 - Let's vote on the market proposal + +# IMPORTANT: When voting for a proposal on the Vega Testnet, typically a single +# YES vote from the proposer will not be enough to vote the market into +# existence. This is because of the network minimum threshold for voting on +# proposals, this threshold for market proposals this is currently a 66% +# majority vote either YES or NO. A proposer should enlist the help/YES votes +# from other community members, ideally on the Community forums +# (https://community.vega.xyz/c/testnet) or Discord (https://vega.xyz/discord) + +# Further documentation on proposal voting and review here: +# https://docs.testnet.vega.xyz/docs/api-howtos/proposals/ + +# __prepare_vote: +# Prepare a vote for the proposal +vote = { + "vote": { + "partyId": pubkey, + "value": "VALUE_YES", # Can be either VALUE_YES or VALUE_NO + "proposalId": proposal_id, + } +} + +url = f"{node_url_rest}/governance/prepare/vote" +response = requests.post(url, json=vote) +helpers.check_response(response) +prepared_vote = response.json() +# :prepare_vote__ + +# Debugging +# print("Prepared vote:\n", prepared_vote, "\n") + +# __sign_tx_vote: +# Sign the prepared vote transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_vote["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_vote__ + +print("Signed vote on proposal and sent to Vega") + +# Debugging +# print("Signed transaction:\n", response.json(), "\n") + +print("Waiting for vote on proposal to succeed or fail...", end="", flush=True) +done = False +while not done: + time.sleep(0.5) + my_proposals = requests.get(node_url_rest + "/parties/" + + pubkey + "/proposals") + if my_proposals.status_code != 200: + continue + + for n in my_proposals.json()["data"]: + if n["proposal"]["reference"] == proposal_ref: + if n["proposal"]["state"] != "STATE_OPEN": + print(n["proposal"]["state"]) + if n["proposal"]["state"] == "STATE_ENACTED": + done = True + break + elif n["proposal"]["state"] == "STATE_PASSED": + print("proposal vote has succeeded, waiting for enactment") + else: + print(n) + exit(1) diff --git a/rest/examples/python/submit-amend-cancel-order.py b/rest/examples/python/submit-amend-cancel-order.py new file mode 100644 index 00000000..eb797ee0 --- /dev/null +++ b/rest/examples/python/submit-amend-cancel-order.py @@ -0,0 +1,260 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import requests +import time +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +url = f"{node_url_rest}/markets" +response = requests.get(url) +helpers.check_response(response) +marketID = response.json()["markets"][0]["id"] +# :get_market__ + +assert marketID != "" +resp = response.json() +marketName = resp["markets"][0]["tradableInstrument"]["instrument"]["name"] +print(f"Market found: {marketID} {marketName}") + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_expiry_time: +# Request the current blockchain time, calculate an expiry time +response = requests.get(f"{node_url_rest}/time") +helpers.check_response(response) +blockchain_time = int(response.json()["timestamp"]) +expiresAt = str(int(blockchain_time + 120 * 1e9)) # expire in 2 minutes +# :get_expiry_time__ + +assert blockchain_time > 0 +print(f"Blockchain time: {blockchain_time}") + +############################################################################### +# S U B M I T O R D E R # +############################################################################### + +# __prepare_submit_order: +# Prepare a submit order message +req = { + "submission": { + "marketId": marketID, + "price": "1", # Note: price is an integer. For example 123456 + "size": "100", # is a price of 1.23456, assuming 5 decimal places. + "side": "SIDE_BUY", + "timeInForce": "TIME_IN_FORCE_GTT", + "expiresAt": expiresAt, + "type": "TYPE_LIMIT", + } +} +url = f"{node_url_rest}/orders/prepare/submit" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_order = response.json() +# :prepare_submit_order__ + +order_ref = prepared_order["submitId"] +print(f"Prepared order, ref: {order_ref}") + +# __sign_tx_order: +# Sign the prepared order transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_order["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_order__ + +print("Signed order and sent to Vega") + +# Wait for order submission to be included in a block +print("Waiting for blockchain...", end="", flush=True) +url = f"{node_url_rest}/orders/{order_ref}" +response = requests.get(url) +while response.status_code != 200: + time.sleep(0.5) + print(".", end="", flush=True) + response = requests.get(url) + +response_json = response.json() +orderID = response_json["order"]["id"] +orderStatus = response_json["order"]["status"] +createVersion = response_json["order"]["version"] +orderReason = response_json["order"]["reason"] + +print(f"\nOrder processed, ID: {orderID}, " + f"Status: {orderStatus}, Version: {createVersion}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +############################################################################### +# A M E N D O R D E R # +############################################################################### + +# __prepare_amend_order: +# Prepare the amend order message +req = { + "amendment": { + "orderId": orderID, + "marketId": marketID, + "price": { + "value": "2" + }, + "sizeDelta": "-25", + "timeInForce": "TIME_IN_FORCE_GTC", + } +} +url = f"{node_url_rest}/orders/prepare/amend" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_amend = response.json() +blob = prepared_amend["blob"] +# :prepare_amend_order__ + +print(f"Amendment prepared for order ID: {orderID}") + +# __sign_tx_amend: +# Sign the prepared order transaction for amendment +# Note: Setting propagate to true will also submit to a Vega node +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_amend__ + +print("Signed amendment and sent to Vega") + +# Wait for amendment to be included in a block +print("Waiting for blockchain...") +time.sleep(3) +url = f"{node_url_rest}/orders/{order_ref}" +response = requests.get(url) +response_json = response.json() +orderID = response_json["order"]["id"] +orderPrice = response_json["order"]["price"] +orderSize = response_json["order"]["size"] +orderTif = response_json["order"]["timeInForce"] +orderStatus = response_json["order"]["status"] +orderVersion = response_json["order"]["version"] +orderReason = response_json["order"]["reason"] + +print("Amended Order:") +print(f"ID: {orderID}, Status: {orderStatus}, Price(Old): 1, " + f"Price(New): {orderPrice}, Size(Old): 100, Size(New): {orderSize}, " + f"TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): {orderTif}, " + f"Version(Old): {createVersion}, Version(new): {orderVersion}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +############################################################################### +# C A N C E L O R D E R S # +############################################################################### + +# Select the mode to cancel orders from the +# following (comment out others), default = 3 + +# __prepare_cancel_order_req1: +# 1 - Cancel single order for the signing party (pubkey) +req = { + "cancellation": { + # Include market and order identifier fields to cancel single order. + "marketId": marketID, + "orderId": orderID, + } +} +# :prepare_cancel_order_req1__ + +# __prepare_cancel_order_req2: +# 2 - Cancel all orders on market for the signing party (pubkey) +req = { + "cancellation": { + # Only include market identifier field. + "marketId": marketID, + } +} +# :prepare_cancel_order_req2__ + +# __prepare_cancel_order_req3: +# 3 - Cancel all orders on all markets for the signing party (pubkey) +req = { + "cancellation": {} +} +# :prepare_cancel_order_req3__ + +# __prepare_cancel_order: +# Prepare the cancel order message +url = f"{node_url_rest}/orders/prepare/cancel" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_cancel = response.json() +blob = prepared_cancel["blob"] +# :prepare_cancel_order__ + +print(f"Cancellation prepared for order ID: {orderID}") + +# __sign_tx_cancel: +# Sign the prepared order transaction for cancellation +# Note: Setting propagate to true will also submit to a Vega node +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_cancel__ + +print("Signed cancellation and sent to Vega") + +# Wait for cancellation to be included in a block +print("Waiting for blockchain...") +time.sleep(3) +url = f"{node_url_rest}/orders/{order_ref}" +response = requests.get(url) +response_json = response.json() +orderID = response_json["order"]["id"] +orderStatus = response_json["order"]["status"] +orderReason = response_json["order"]["reason"] + +print("Cancelled Order:") +print(f"ID: {orderID}, Status: {orderStatus}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") + +# Completed. diff --git a/rest/examples/python/submit-amend-pegged-order.py b/rest/examples/python/submit-amend-pegged-order.py new file mode 100644 index 00000000..e89329a2 --- /dev/null +++ b/rest/examples/python/submit-amend-pegged-order.py @@ -0,0 +1,196 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import requests +import time +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +url = f"{node_url_rest}/markets" +response = requests.get(url) +helpers.check_response(response) +marketID = response.json()["markets"][0]["id"] +# :get_market__ + +assert marketID != "" +resp = response.json() +marketName = resp["markets"][0]["tradableInstrument"]["instrument"]["name"] +print(f"Market found: {marketID} {marketName}") + +############################################################################### +# B L O C K C H A I N T I M E # +############################################################################### + +# __get_expiry_time: +# Request the current blockchain time, calculate an expiry time +response = requests.get(f"{node_url_rest}/time") +helpers.check_response(response) +blockchain_time = int(response.json()["timestamp"]) +expiresAt = str(int(blockchain_time + 120 * 1e9)) # expire in 2 minutes +# :get_expiry_time__ + +assert blockchain_time > 0 +print(f"Blockchain time: {blockchain_time}") + +############################################################################### +# S U B M I T P E G G E D O R D E R # +############################################################################### + +# __prepare_submit_pegged_order: +# Prepare a submit order message with a pegged BUY order +req = { + "submission": { + "marketId": marketID, + "size": "50", + "side": "SIDE_BUY", + "timeInForce": "TIME_IN_FORCE_GTT", + "expiresAt": expiresAt, + "type": "TYPE_LIMIT", + "peggedOrder": { + "offset": "-5", + "reference": "PEGGED_REFERENCE_MID" + } + } +} +url = f"{node_url_rest}/orders/prepare/submit" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_order = response.json() +# :prepare_submit_pegged_order__ + +order_ref = prepared_order["submitId"] +print(f"Prepared pegged order, ref: {order_ref}") + +# __sign_tx_pegged_order: +# Sign the prepared pegged order transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_order["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_pegged_order__ + +print("Signed pegged order and sent to Vega") + +# Wait for order submission to be included in a block +print("Waiting for blockchain...", end="", flush=True) +url = f"{node_url_rest}/orders/{order_ref}" +response = requests.get(url) +while response.status_code != 200: + time.sleep(0.5) + print(".", end="", flush=True) + response = requests.get(url) + +response_json = response.json() +orderID = response_json["order"]["id"] +orderStatus = response_json["order"]["status"] +orderPegged = response_json["order"]["peggedOrder"] +createVersion = response_json["order"]["version"] +orderReason = response_json["order"]["reason"] +print(f"\nPegged order processed, ID: {orderID}, " + f"Status: {orderStatus}, Version: {createVersion}") +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") +else: + print(f"Pegged at: {orderPegged}") + +############################################################################### +# A M E N D P E G G E D O R D E R # +############################################################################### + +# __prepare_amend_pegged_order: +# Prepare the amend order message +req = { + "amendment": { + "orderId": orderID, + "marketId": marketID, + "sizeDelta": "25", + "timeInForce": "TIME_IN_FORCE_GTC", + "peggedReference": "PEGGED_REFERENCE_BEST_BID", + "peggedOffset": "-100", + } +} +url = f"{node_url_rest}/orders/prepare/amend" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_amend = response.json() +blob = prepared_amend["blob"] +# :prepare_amend_pegged_order__ + +print(f"Amendment prepared for order ID: {orderID}") + +# __sign_tx_pegged_amend: +# Sign the prepared pegged order transaction for amendment +# Note: Setting propagate to true will also submit to a Vega node +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_pegged_amend__ + +print("Signed pegged order amendment and sent to Vega") + +# Wait for amendment to be included in a block +print("Waiting for blockchain...") +time.sleep(4) +url = f"{node_url_rest}/orders/{order_ref}" +response = requests.get(url) +response_json = response.json() +orderID = response_json["order"]["id"] +orderPrice = response_json["order"]["price"] +orderSize = response_json["order"]["size"] +orderTif = response_json["order"]["timeInForce"] +orderStatus = response_json["order"]["status"] +orderPegged = response_json["order"]["peggedOrder"] +orderVersion = response_json["order"]["version"] +orderReason = response_json["order"]["reason"] + +print("Amended pegged order:") +print(f"ID: {orderID}, Status: {orderStatus}, " + f"Size(Old): 50, Size(New): {orderSize}, " + f"TimeInForce(Old): TIME_IN_FORCE_GTT, TimeInForce(New): {orderTif}, " + f"Version(Old): {createVersion}, Version(new): {orderVersion}") + +if orderStatus == "STATUS_REJECTED": + print(f"Rejection reason: {orderReason}") +else: + print(f"Pegged at: {orderPegged}") + + +# Completed. diff --git a/rest/examples/python/submit-liquidity-provision-order.py b/rest/examples/python/submit-liquidity-provision-order.py new file mode 100644 index 00000000..33a8566b --- /dev/null +++ b/rest/examples/python/submit-liquidity-provision-order.py @@ -0,0 +1,234 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) +- Vega node (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +import json +import requests +import time +import helpers + +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey + +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") + +############################################################################### +# F I N D M A R K E T # +############################################################################### + +# __get_market: +# Request the identifier for the market to place on +url = f"{node_url_rest}/markets" +response = requests.get(url) +helpers.check_response(response) +marketID = response.json()["markets"][0]["id"] +# :get_market__ + + +assert marketID != "" +resp = response.json() +marketName = resp["markets"][0]["tradableInstrument"]["instrument"]["name"] +print(f"Market found: {marketID} {marketName}") + +############################################################################### +# L I S T L I Q U I D I T Y P R O V I S I O N S # +############################################################################### + +# __get_liquidity_provisions: +# Request liquidity provisions for the market +# Specify party ID below (if needed), otherwise all liquidity +# provisions for the market will be returned +partyID = "" +url = "{base}/liquidity-provisions/party/{party}/market/{marketId}".format( + base=node_url_rest, party=partyID, marketId=marketID +) +response = requests.get(url) +helpers.check_response(response) +response_json = response.json() + +print("Liquidity provisions:\n{}".format( + json.dumps(response_json, indent=2, sort_keys=True) +)) +# :get_liquidity_provisions__ + +############################################################################### +# S U B M I T L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# Note: commitmentAmount is an integer. For example 123456 is a +# price of 1.23456, for a market which is configured to have a +# precision of 5 decimal places. + +# __prepare_liquidity_order: +# Prepare a liquidity commitment transaction message +req = { + "submission": { + "marketId": marketID, + "commitmentAmount": "100", + "fee": "0.01", + "buys": [ + { + "offset": "-1", + "proportion": "1", + "reference": "PEGGED_REFERENCE_MID" + }, + { + "offset": "-2", + "proportion": "2", + "reference": "PEGGED_REFERENCE_MID" + } + ], + "sells": [ + { + "offset": "1", + "proportion": "1", + "reference": "PEGGED_REFERENCE_MID" + }, + { + "offset": "2", + "proportion": "2", + "reference": "PEGGED_REFERENCE_MID" + }, + { + "offset": "3", + "proportion": "5", + "reference": "PEGGED_REFERENCE_MID" + } + ] + } +} +url = f"{node_url_rest}/liquidity-provisions/prepare/submit" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_order = response.json() +# :prepare_liquidity_order__ + +print(f"Prepared liquidity commitment for market: {marketID} {marketName}") + +# __sign_tx_liquidity_order: +# Sign the prepared liquidity commitment transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_order["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) +# :sign_tx_liquidity_order__ + +print("Signed liquidity commitment and sent to Vega") + +# Comment out the lines below to add a cancellation of the LP commitment +print("To add cancellation step, uncomment line 180 of the script file") +exit(0) + +############################################################################### +# A M E N D L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# __amend_liquidity_order: +# Prepare a liquidity commitment order message (it will now serve as an +# amendment request): modify fields to be amended + +req = { + "submission": { + "marketId": marketID, + "commitmentAmount": "500", + "fee": "0.005", + "buys": [ + { + "offset": "-1", + "proportion": "1", + "reference": "PEGGED_REFERENCE_MID" + } + ], + "sells": [ + { + "offset": "1", + "proportion": "1", + "reference": "PEGGED_REFERENCE_MID" + } + ] + } +} +url = f"{node_url_rest}/liquidity-provisions/prepare/submit" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_order = response.json() +# :amend_liquidity_order__ + +print("Prepared liquidity commitment (amendment)" + + " for market: {marketID} {marketName}") + +# Sign the prepared liquidity commitment transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_order["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) + +print("Signed liquidity commitment (amendment) and sent to Vega") + +# Completed. + +time.sleep(10) + +############################################################################### +# C A N C E L L I Q U I D I T Y C O M M I T M E N T # +############################################################################### + +# __cancel_liquidity_order: +# Prepare a liquidity commitment order message (it will now serve as a +# cancellation request): set commitmentAmount to 0, that transaction may +# get rejected if removing previously supplied liquidity +# will result in insufficient liquidity for the market + +req = { + "submission": { + "marketId": marketID, + "commitmentAmount": "0" + } +} +url = f"{node_url_rest}/liquidity-provisions/prepare/submit" +response = requests.post(url, json=req) +helpers.check_response(response) +prepared_order = response.json() +# :cancel_liquidity_order__ + +print("Prepared liquidity commitment (cancellation)" + + " for market: {marketID} {marketName}") + +# Sign the prepared liquidity commitment transaction +# Note: Setting propagate to true will also submit to a Vega node +blob = prepared_order["blob"] +req = {"tx": blob, "pubKey": pubkey, "propagate": True} +url = f"{wallet_server_url}/api/v1/messages" +response = requests.post(url, headers=headers, json=req) +helpers.check_response(response) + +print("Signed liquidity commitment (cancellation) and sent to Vega") + +# Completed. diff --git a/rest/examples/python/submit-order.py b/rest/examples/python/submit-order.py index d5e69c18..76f71e4e 100644 --- a/rest/examples/python/submit-order.py +++ b/rest/examples/python/submit-order.py @@ -21,93 +21,17 @@ import json import requests -import sys -from typing import Any, Dict - import helpers -# --- Edit these values below --- -node_url_rest = ">> e.g. https://lb.testnet.vega.xyz" -walletserver_url = ">> Vega-hosted wallet: https://wallet.testnet.vega.xyz" -walletserver_url = ">> self-hosted wallet: http://localhost:1789" -wallet_name = ">> your wallet name here" -wallet_passphrase = ">> your passphrase here" -# --- Edit these values above --- - -if "--ci" in sys.argv: - node_url_rest = helpers.get_from_env("NODE_URL_REST") - walletserver_url = helpers.get_from_env("WALLETSERVER_URL") - wallet_name = helpers.get_from_env("WALLET_NAME") - wallet_passphrase = helpers.get_from_env("WALLET_PASSPHRASE") - -if not helpers.check_url(node_url_rest): - print("Invalid Vega node URL (REST)") - print('Edit this script and look for "Edit these values"') - exit(1) - -if not helpers.check_url(walletserver_url): - print("Invalid wallet server URL") - print('Edit this script and look for "Edit these values"') - exit(1) - -if not helpers.check_var(wallet_name): - print("Invalid wallet name") - print('Edit this script and look for "Edit these values"') - exit(1) - -if not helpers.check_var(wallet_passphrase): - print("Invalid wallet passphrase") - print('Edit this script and look for "Edit these values"') - exit(1) - -# Help guide users against including api version suffix on url -walletserver_url = helpers.fix_walletserver_url(walletserver_url) - -# __create_wallet: -CREATE_NEW_WALLET = False -if CREATE_NEW_WALLET: - # EITHER: Create new wallet - url = f"{walletserver_url}/api/v1/wallets" -else: - # OR: Log in to existing wallet - url = f"{walletserver_url}/api/v1/auth/token" +# Vega wallet interaction helper, see login.py for detail +from login import token, pubkey -req: Dict[str, Any] +# Load Vega network URLs, these are set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") +node_url_rest = helpers.get_from_env("NODE_URL_REST") -# Make request to create new wallet or log in to existing wallet -req = {"wallet": wallet_name, "passphrase": wallet_passphrase} -response = requests.post(url, json=req) -helpers.check_response(response) - -# Pull out the token and make a headers dict -token = response.json()["token"] -headers = {"Authorization": f"Bearer {token}"} -# :create_wallet__ - -# __generate_keypair: -GENERATE_NEW_KEYPAIR = False -pubKey = "" -if GENERATE_NEW_KEYPAIR: - # EITHER: Generate a new keypair - req = { - "passphrase": wallet_passphrase, - "meta": [{"key": "alias", "value": "my_key_alias"}], - } - url = f"{walletserver_url}/api/v1/keys" - response = requests.post(url, headers=headers, json=req) - helpers.check_response(response) - pubKey = response.json()["key"]["pub"] -else: - # OR: List existing keypairs - url = f"{walletserver_url}/api/v1/keys" - response = requests.get(url, headers=headers) - helpers.check_response(response) - keys = response.json()["keys"] - assert len(keys) > 0 - pubKey = keys[0]["pub"] -# :generate_keypair__ - -assert pubKey != "" +assert pubkey != "" # __get_market: # Next, get a Market ID @@ -121,13 +45,13 @@ # Next, prepare a SubmitOrder response = requests.get(f"{node_url_rest}/time") helpers.check_response(response) -blockchaintime = int(response.json()["timestamp"]) -expiresAt = str(int(blockchaintime + 120 * 1e9)) # expire in 2 minutes +blockchainTime = int(response.json()["timestamp"]) +expiresAt = str(int(blockchainTime + 120 * 1e9)) # expire in 2 minutes req = { "submission": { "marketId": marketID, - "partyId": pubKey, + "partyId": pubkey, "price": "100000", # Note: price is an integer. For example 123456 "size": "100", # is a price of 1.23456, assuming 5 decimal places. "side": "SIDE_BUY", @@ -149,10 +73,11 @@ # __sign_tx: # Wallet server: Sign the prepared transaction blob = preparedOrder["blob"] -req = {"tx": blob, "pubKey": pubKey, "propagate": False} +req = {"tx": blob, "pubKey": pubkey, "propagate": False} print("Request for SignTx:") print(json.dumps(req, indent=2, sort_keys=True)) -url = f"{walletserver_url}/api/v1/messages" +url = f"{wallet_server_url}/api/v1/messages" +headers = {"Authorization": f"Bearer {token}"} response = requests.post(url, headers=headers, json=req) helpers.check_response(response) signedTx = response.json()["signedTx"] diff --git a/rest/examples/python/wallet.py b/rest/examples/python/wallet.py new file mode 100644 index 00000000..33c9cf29 --- /dev/null +++ b/rest/examples/python/wallet.py @@ -0,0 +1,132 @@ +#!/usr/bin/python3 + +""" +Script language: Python3 + +Talks to: +- Vega wallet (REST) + +Apps/Libraries: +- REST: requests (https://pypi.org/project/requests/) +""" + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +import base64 +import json +import requests +import helpers + +wallet_name = helpers.random_string() +wallet_passphrase = helpers.random_string() + +# Load Vega WALLET SERVER URL, this is set using 'source examples-config' +# located in the root folder of the api repository +wallet_server_url = helpers.get_from_env("WALLETSERVER_URL") + +print(f"Creating a new wallet on {wallet_server_url}:") +print(f"- name: {wallet_name}") +print(f"- passphrase: {wallet_passphrase}") + + +# __create_wallet: +# Create a new wallet: +req = {"wallet": wallet_name, "passphrase": wallet_passphrase} +response = requests.post(f"{wallet_server_url}/api/v1/wallets", json=req) +helpers.check_response(response) +token = response.json()["token"] +# :create_wallet__ + + +# The example below uses the credentials we just created +# and in practice you don't need to log in immediately after +# creating a new wallet, as the response already contains the +# token that you need to authenticate with future requests. + + +# __login_wallet: +# Log in to an existing wallet +req = {"wallet": wallet_name, "passphrase": wallet_passphrase} +response = requests.post(f"{wallet_server_url}/api/v1/auth/token", json=req) +helpers.check_response(response) +token = response.json()["token"] +# :login_wallet__ + + +# __generate_keypair: +# Generate a new key pair +headers = {"Authorization": f"Bearer {token}"} +req = { + "passphrase": wallet_passphrase, + "meta": [{"key": "alias", "value": "my_key_alias"}], +} +response = requests.post( + f"{wallet_server_url}/api/v1/keys", headers=headers, json=req +) +helpers.check_response(response) +pubkey = response.json()["key"]["pub"] +# Print key information. Note that the private key is *not* returned. +keypair = response.json()["key"] +print("Generated new keypair:") +print(json.dumps(keypair, indent=2, sort_keys=True)) +# :generate_keypair__ + + +# __get_keys: +# Request all key pairs +headers = {"Authorization": f"Bearer {token}"} +response = requests.get(f"{wallet_server_url}/api/v1/keys", headers=headers) +helpers.check_response(response) +keys = response.json()["keys"] +for key in keys: + print("List key pairs:") + print(json.dumps(key, indent=2, sort_keys=True)) +# :get_keys__ + +pubkey = keys[0]["pub"] + +# __get_key: +# Request a single key pair +headers = {"Authorization": f"Bearer {token}"} +response = requests.get( + f"{wallet_server_url}/api/v1/keys/{pubkey}", headers=headers +) +helpers.check_response(response) +key = response.json()["key"] +print("Get a single keypair:") +print(json.dumps(key, indent=2, sort_keys=True)) +# :get_key__ + + +# __sign_tx: +# Sign a transaction - Note: setting "propagate" to True will also submit the +# tx to Vega node +headers = {"Authorization": f"Bearer {token}"} +blob = b"data returned from a Vega node 'Prepare' call" +tx = base64.b64encode(blob).decode("ascii") +req = {"tx": tx, "pubKey": pubkey, "propagate": False} +response = requests.post( + f"{wallet_server_url}/api/v1/messages/sync", headers=headers, json=req +) +helpers.check_response(response) +signedTx = response.json()["signedTx"] +print("Signed transaction:") +print(json.dumps(signedTx, indent=2, sort_keys=True)) +# :sign_tx__ + + +# __logout_wallet: +# Log out of a wallet +headers = {"Authorization": f"Bearer {token}"} +response = requests.delete( + f"{wallet_server_url}/api/v1/auth/token", headers=headers +) +helpers.check_response(response) +# :logout_wallet__ diff --git a/rest/examples/shell/get-accounts.sh b/rest/examples/shell/get-accounts.sh new file mode 100755 index 00000000..1272d0d4 --- /dev/null +++ b/rest/examples/shell/get-accounts.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +# Script language: bash + +# Talks to: +# - Vega wallet (REST) +# - Vega node (REST) +# +# Apps/Libraries: +# - REST: curl + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +source helpers.sh + +check_url "NODE_URL_REST" || exit 1 +check_url "WALLETSERVER_URL" || exit 1 + +check_var "WALLET_NAME" || exit 1 +check_var "WALLET_PASSPHRASE" || exit 1 + +##################################################################################### +# W A L L E T S E R V I C E # +##################################################################################### + +echo "Logging into wallet: $WALLET_NAME" + +# __login_wallet: +# Log in to an existing wallet +req='{"wallet": "'"$WALLET_NAME"'","passphrase": "'"$WALLET_PASSPHRASE"'"}' +url="$WALLETSERVER_URL/api/v1/auth/token" +response="$(curl -s -XPOST -d "$req" "$url")" +token="$(echo "$response" | jq -r .token)" +# :login_wallet__ + +test "$token" == null && exit 1 +echo "Logged in to wallet successfully" + +# __get_pubkey: +# List key pairs and select public key to use +hdr="Authorization: Bearer $token" +url="$WALLETSERVER_URL/api/v1/keys" +response="$(curl -s -XGET -H "$hdr" "$url")" +pubkey="$(echo "$response" | jq -r '.keys[0].pub')" +# :get_pubkey__ + +test -n "$pubkey" || exit 1 +test "$pubkey" == null && exit 1 +echo "Selected pubkey for signing" + +##################################################################################### +# M A R K E T A C C O U N T S # +##################################################################################### + +# Request a list of markets and select the first one +url="$NODE_URL_REST/markets" +response="$(curl -s "$url")" +marketID="$(echo "$response" | jq -r '.markets[0].id')" +# :get_market__ + +echo "Market found: $marketID" + +# __get_accounts_by_market: +# Request a list of accounts for a market on a Vega network +url="$NODE_URL_REST/markets/$marketID/accounts" +response="$(curl -s "$url")" +accounts="$(echo "$response" | jq -r .accounts)" +echo "Market accounts: +$accounts" +# :get_accounts_by_market__ + +##################################################################################### +# P A R T Y A C C O U N T S # +##################################################################################### + +# __get_accounts_by_party: +# Request a list of accounts for a party (pubkey) on a Vega network +url="$NODE_URL_REST/parties/$pubkey/accounts" +response="$(curl -s "$url")" +accounts="$(echo "$response" | jq -r .accounts)" +echo "Party accounts: +$accounts" +# :get_accounts_by_party__ + +##################################################################################### +# P A R T Y P O S I T I O N S # +##################################################################################### + +# __get_positions_by_party: +# Request a list of positions for a party (pubkey) on a Vega network +url="$NODE_URL_REST/parties/$pubkey/positions" +response="$(curl -s "$url")" +positions="$(echo "$response" | jq -r .positions)" +echo "Party positions: +$positions" +# :get_positions_by_party__ diff --git a/rest/examples/shell/get-fees-margins-estimate.sh b/rest/examples/shell/get-fees-margins-estimate.sh new file mode 100755 index 00000000..6c531917 --- /dev/null +++ b/rest/examples/shell/get-fees-margins-estimate.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash + +# Script language: bash +# +# Talks to: +# - Vega node (REST) +# +# Apps/Libraries: +# - REST: curl + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ + +source helpers.sh + +check_url "NODE_URL_REST" || exit 1 +check_url "WALLETSERVER_URL" || exit 1 + +check_var "WALLET_NAME" || exit 1 +check_var "WALLET_PASSPHRASE" || exit 1 + +##################################################################################### +# W A L L E T S E R V I C E # +##################################################################################### + +echo "Logging into wallet: $WALLET_NAME" + +# __login_wallet: +# Log in to an existing wallet +req='{"wallet": "'"$WALLET_NAME"'","passphrase": "'"$WALLET_PASSPHRASE"'"}' +url="$WALLETSERVER_URL/api/v1/auth/token" +response="$(curl -s -XPOST -d "$req" "$url")" +token="$(echo "$response" | jq -r .token)" +# :login_wallet__ + +test "$token" == null && exit 1 +echo "Logged in to wallet successfully" + +# __get_pubkey: +# List key pairs and select public key to use +hdr="Authorization: Bearer $token" +url="$WALLETSERVER_URL/api/v1/keys" +response="$(curl -s -XGET -H "$hdr" "$url")" +pubKey="$(echo "$response" | jq -r '.keys[0].pub')" +# :get_pubkey__ + +test -n "$pubKey" || exit 1 +test "$pubKey" == null && exit 1 +echo "Selected pubkey for signing" + +##################################################################################### +# F I N D M A R K E T # +##################################################################################### + +# __get_market: +# Request the identifier for the market to place on +url="$NODE_URL_REST/markets" +response="$(curl -s "$url")" +marketID="$(echo "$response" | jq -r '.markets[0].id')" +# :get_market__ + +echo "Market found: $marketID" + +##################################################################################### +# F E E E S T I M A T I O N # +##################################################################################### + +# __get_fees_estimate: +# Request to estimate trading fees on a Vega network +cat >req.json <req.json <>" "e.g." "example" ; do + if echo "$var_value" | grep -qF "$substr" ; then + echo "Invalid $var_name - contains \"$substr\"" + return 0 + fi + done + return 1 +} diff --git a/rest/examples/shell/submit-amend-cancel-order.sh b/rest/examples/shell/submit-amend-cancel-order.sh new file mode 100755 index 00000000..1e23ec15 --- /dev/null +++ b/rest/examples/shell/submit-amend-cancel-order.sh @@ -0,0 +1,288 @@ +#!/usr/bin/env bash + +# Script language: bash + +# Talks to: +# - Vega wallet (REST) +# - Vega node (REST) +# +# Apps/Libraries: +# - REST: curl + +# Note: this file uses smart-tags in comments to section parts of the code to +# show them as snippets in our documentation. They are not necessary to be +# included when creating your own custom code. +# +# Example of smart-tags: +# __something: +# some code here +# :something__ +# + +source helpers.sh + +check_url "NODE_URL_REST" || exit 1 +check_url "WALLETSERVER_URL" || exit 1 + +check_var "WALLET_NAME" || exit 1 +check_var "WALLET_PASSPHRASE" || exit 1 + +##################################################################################### +# W A L L E T S E R V I C E # +##################################################################################### + +echo "Logging into wallet: $WALLET_NAME" + +# __login_wallet: +# Log in to an existing wallet +req='{"wallet": "'"$WALLET_NAME"'","passphrase": "'"$WALLET_PASSPHRASE"'"}' +url="$WALLETSERVER_URL/api/v1/auth/token" +response="$(curl -s -XPOST -d "$req" "$url")" +token="$(echo "$response" | jq -r .token)" +# :login_wallet__ + +test "$token" == null && exit 1 +echo "Logged in to wallet successfully" + +# __get_pubkey: +# List key pairs and select public key to use +hdr="Authorization: Bearer $token" +url="$WALLETSERVER_URL/api/v1/keys" +response="$(curl -s -XGET -H "$hdr" "$url")" +pubKey="$(echo "$response" | jq -r '.keys[0].pub')" +# :get_pubkey__ + +test -n "$pubKey" || exit 1 +test "$pubKey" == null && exit 1 +echo "Selected pubkey for signing" + +##################################################################################### +# F I N D M A R K E T # +##################################################################################### + +# __get_market: +# Request the identifier for the market to place on +url="$NODE_URL_REST/markets" +response="$(curl -s "$url")" +marketID="$(echo "$response" | jq -r '.markets[0].id')" +# :get_market__ + +echo "Market found: $marketID" + +##################################################################################### +# B L O C K C H A I N T I M E # +##################################################################################### + +# __get_expiry_time: +# Request the current blockchain time, calculate an expiry time +url="$NODE_URL_REST/time" +response="$(curl -s "$url")" +blockchaintime="$(echo "$response" | jq -r .timestamp)" +expiresAt="$((blockchaintime+120*10**9))" # expire in 2 minutes +# :get_expiry_time__ + +echo "Blockchain time: $expiresAt" + +##################################################################################### +# S U B M I T O R D E R # +##################################################################################### + +# __prepare_submit_order: +# Prepare a submit order message +# Note: price is an integer. For example 123456 is a price of 1.23456, +# assuming 5 decimal places. +cat >req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <req.json <' call +blob="ZGF0YSByZXR1cm5lZCBmcm9tIGEgVmVnYSBub2RlICdQcmVwYXJlPG9wZXJhdGlvbj4nIGNhbGw=" +test "$blob" == null && exit 1 +cat >req.json <