diff --git a/.gitignore b/.gitignore index 1124e88..b34d88c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ FIX/sessions __pycache__/ *.pyc *.pyo -FIX/example.cfg \ No newline at end of file +FIX/example.cfg +t_* \ No newline at end of file diff --git a/REST/prime_cancel_entity_futures_sweep.py b/REST/prime_cancel_entity_futures_sweep.py new file mode 100644 index 0000000..de2361e --- /dev/null +++ b/REST/prime_cancel_entity_futures_sweep.py @@ -0,0 +1,52 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') + +parser = argparse.ArgumentParser(description='Cancel pending futures sweep for an entity') +parser.add_argument('--entity-id', type=str, required=True, help='Entity ID') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/entities/{args.entity_id}/futures/sweeps' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'DELETE' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.delete(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_cancel_order.py b/REST/prime_cancel_order.py index c9c5385..05d6a0a 100644 --- a/REST/prime_cancel_order.py +++ b/REST/prime_cancel_order.py @@ -12,8 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import sys +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests, sys + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_claim_wallet_staking_rewards.py b/REST/prime_claim_wallet_staking_rewards.py new file mode 100644 index 0000000..fa6b541 --- /dev/null +++ b/REST/prime_claim_wallet_staking_rewards.py @@ -0,0 +1,67 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +parser = argparse.ArgumentParser(description='Claim wallet staking rewards (alpha)') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--amount', type=str, help='Amount to claim (ETH only, defaults to maximum available)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/staking/claim_rewards' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'idempotency_key': str(uuid.uuid4()) +} + +if args.amount: + payload['inputs'] = { + 'amount': args.amount + } + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_address_book_entry.py b/REST/prime_create_address_book_entry.py index 0544fbb..b39f1e7 100644 --- a/REST/prime_create_address_book_entry.py +++ b/REST/prime_create_address_book_entry.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_allocations.py b/REST/prime_create_allocations.py index b9cb133..1958d34 100644 --- a/REST/prime_create_allocations.py +++ b/REST/prime_create_allocations.py @@ -11,10 +11,20 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, uuid, os, base64, requests, argparse, sys +import argparse +import base64 +import hashlib +import hmac +import json +import os +import sys +import time +import uuid from urllib.parse import urlparse -# Must be entity or organization API key +import requests + + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') @@ -45,7 +55,7 @@ allocation_legs = [] for dest_portfolio_id in args.destination_portfolio_ids: allocation_legs.append({ - 'allocation_leg_id': allocation_leg_id, + 'allocation_leg_id': str(allocation_leg_id), 'destination_portfolio_id': dest_portfolio_id, 'amount': str(amount) }) diff --git a/REST/prime_create_conversion.py b/REST/prime_create_conversion.py index de6140d..48cb1c9 100644 --- a/REST/prime_create_conversion.py +++ b/REST/prime_create_conversion.py @@ -12,35 +12,44 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') -wallet_id = 'WALLET_UUID' +# Parse command line arguments +parser = argparse.ArgumentParser(description='Create a conversion between USD, USDC, and PYUSD') +parser.add_argument('--wallet-id', type=str, required=True, help='Source wallet ID') +parser.add_argument('--amount', type=str, required=True, help='Amount to convert') +parser.add_argument('--destination', type=str, required=True, help='Destination wallet ID') +parser.add_argument('--source-symbol', type=str, required=True, choices=['USD', 'USDC', 'PYUSD'], help='Source symbol (USD, USDC, or PYUSD)') +parser.add_argument('--destination-symbol', type=str, required=True, choices=['USD', 'USDC', 'PYUSD'], help='Destination symbol (USD, USDC, or PYUSD)') -uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{wallet_id}/conversion' +args = parser.parse_args() -timestamp = str(int(time.time())) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/conversion' -# only supports conversions between USDC and USD -amount = '1' -destination = 'DESTINATION_WALLET_UUID' -idempotency_key = uuid.uuid4() -source_symbol = 'USD' -destination_symbol = 'USDC' +timestamp = str(int(time.time())) +idempotency_key = str(uuid.uuid4()) payload = { - 'portfolio_id': PORTFOLIO_ID, - 'wallet_id': wallet_id, - 'amount': amount, - 'destination': destination, - 'idempotency_key': str(idempotency_key), - 'source_symbol': source_symbol, - 'destination_symbol': destination_symbol + 'amount': args.amount, + 'destination': args.destination, + 'idempotency_key': idempotency_key, + 'source_symbol': args.source_symbol, + 'destination_symbol': args.destination_symbol } url_path = urlparse(uri).path @@ -52,9 +61,10 @@ 'X-CB-ACCESS-TIMESTAMP': timestamp, 'X-CB-ACCESS-KEY': API_KEY, 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, - 'Accept': 'application/json' + 'Accept': 'application/json', + 'Content-Type': 'application/json' } -response = requests.post(uri, json=payload, headers=headers) +response = requests.post(uri, headers=headers, data=json.dumps(payload)) parsed_response = json.loads(response.text) print(json.dumps(parsed_response, indent=3)) \ No newline at end of file diff --git a/REST/prime_create_locate.py b/REST/prime_create_locate.py new file mode 100644 index 0000000..a1671e4 --- /dev/null +++ b/REST/prime_create_locate.py @@ -0,0 +1,63 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Create a new locate') +parser.add_argument('--symbol', type=str, required=True, help='Asset symbol (e.g., BTC, ETH)') +parser.add_argument('--amount', type=str, required=True, help='Amount to locate') +parser.add_argument('--locate-date', type=str, required=True) + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/locates' +timestamp = str(int(time.time())) + +payload = { + 'portfolio_id': PORTFOLIO_ID, + 'symbol': args.symbol, + 'amount': args.amount, + 'locate_date': args.locate_date +} + +url_path = urlparse(uri).path +message = timestamp + 'POST' + url_path + json.dumps(payload) +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.post(uri, json=payload, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_onchain_address_book_entry.py b/REST/prime_create_onchain_address_book_entry.py new file mode 100644 index 0000000..3eb315f --- /dev/null +++ b/REST/prime_create_onchain_address_book_entry.py @@ -0,0 +1,77 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Create onchain address book entry (address group)') +parser.add_argument('--group-id', type=str, required=True, help='Address group ID') +parser.add_argument('--group-name', type=str, required=True, help='Name for the address group') +parser.add_argument('--network-type', type=str, required=True, choices=['NETWORK_TYPE_UNSPECIFIED', 'NETWORK_TYPE_EVM', 'NETWORK_TYPE_SOLANA'], help='Network type') +parser.add_argument('--address-name', type=str, required=True, help='Name for the address entry') +parser.add_argument('--address', type=str, required=True, help='Blockchain address') +parser.add_argument('--chain-ids', type=str, required=True, help='Comma-separated list of chain IDs') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/onchain_address_group' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'address_group': { + 'id': args.group_id, + 'name': args.group_name, + 'network_type': args.network_type, + 'addresses': [ + { + 'name': args.address_name, + 'address': args.address, + 'chain_ids': args.chain_ids.split(',') + } + ] + } +} + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_onchain_transaction.py b/REST/prime_create_onchain_transaction.py new file mode 100644 index 0000000..0933833 --- /dev/null +++ b/REST/prime_create_onchain_transaction.py @@ -0,0 +1,88 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Create an onchain blockchain transaction') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--raw-txn', type=str, required=True, help='Raw unsigned transaction hex (supports EVM and Solana)') +parser.add_argument('--skip-broadcast', action='store_true', help='Skip broadcasting the transaction') +parser.add_argument('--rpc-url', type=str, help='Custom RPC URL') +parser.add_argument('--chain-id', type=str, help='EVM chain ID (required for EVM transactions)') +parser.add_argument('--network-name', type=str, help='Network name (required for EVM transactions, e.g., ethereum-mainnet, base-mainnet)') +parser.add_argument('--disable-dynamic-gas', action='store_true', help='Disable dynamic gas pricing') +parser.add_argument('--disable-dynamic-nonce', action='store_true', help='Disable dynamic nonce') +parser.add_argument('--replaced-txn-id', type=str, help='Transaction ID being replaced') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/onchain_transaction' +timestamp = str(int(time.time())) + +payload = { + 'raw_unsigned_txn': args.raw_txn, + 'rpc': { + 'skip_broadcast': args.skip_broadcast + } +} + +# Add optional RPC URL +if args.rpc_url: + payload['rpc']['url'] = args.rpc_url + +# Add EVM parameters if chain_id or network_name provided +if args.chain_id or args.network_name or args.disable_dynamic_gas or args.disable_dynamic_nonce or args.replaced_txn_id: + payload['evm_params'] = {} + if args.chain_id: + payload['evm_params']['chain_id'] = args.chain_id + if args.network_name: + payload['evm_params']['network_name'] = args.network_name + if args.disable_dynamic_gas: + payload['evm_params']['disable_dynamic_gas'] = True + if args.disable_dynamic_nonce: + payload['evm_params']['disable_dynamic_nonce'] = True + if args.replaced_txn_id: + payload['evm_params']['replaced_transaction_id'] = args.replaced_txn_id + +url_path = urlparse(uri).path +message = timestamp + 'POST' + url_path + json.dumps(payload) +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.post(uri, json=payload, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_order.py b/REST/prime_create_order.py index 6658629..dcd4ec3 100644 --- a/REST/prime_create_order.py +++ b/REST/prime_create_order.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_order_preview.py b/REST/prime_create_order_preview.py index b73e478..a9f51b8 100644 --- a/REST/prime_create_order_preview.py +++ b/REST/prime_create_order_preview.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_rfq_always_accept.py b/REST/prime_create_rfq_always_accept.py index aac4036..053c4c3 100644 --- a/REST/prime_create_rfq_always_accept.py +++ b/REST/prime_create_rfq_always_accept.py @@ -12,23 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse +import base64 +import hashlib +import hmac +import json import os import sys -import json import time import uuid -import hmac -import hashlib -import base64 -import requests -import argparse from urllib.parse import urlparse -# ------------------------------------------------------------------------------ -# Argument Parsing -# Example usage: -# python prime_create_rfq_always_accept.py --product SOL-USD --side BUY --size 0.5 --limit 350 -# ------------------------------------------------------------------------------ +import requests + parser = argparse.ArgumentParser( description="Create and accept an RFQ using Coinbase Prime." ) diff --git a/REST/prime_create_rfq_compare_clob.py b/REST/prime_create_rfq_compare_clob.py index 51ee1f0..daf207d 100644 --- a/REST/prime_create_rfq_compare_clob.py +++ b/REST/prime_create_rfq_compare_clob.py @@ -12,18 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse +import base64 +import hashlib +import hmac +import json import os import sys -import json import time import uuid -import hmac -import base64 -import hashlib -import requests -import argparse from urllib.parse import urlparse +import requests + # ------------------------------------------------------------------------------ # Command-line arguments # Usage example: diff --git a/REST/prime_create_stake_delegate.py b/REST/prime_create_stake_delegate.py new file mode 100644 index 0000000..9126e98 --- /dev/null +++ b/REST/prime_create_stake_delegate.py @@ -0,0 +1,60 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Initiate staking delegation for a wallet') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID to stake') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/staking/initiate' +timestamp = str(int(time.time())) +idempotency_key = str(uuid.uuid4()) + +payload = { + 'idempotency_key': idempotency_key, +} + +url_path = urlparse(uri).path +message = timestamp + 'POST' + url_path + json.dumps(payload) +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.post(uri, json=payload, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_transfer.py b/REST/prime_create_transfer.py index 83325ad..fe3fad8 100644 --- a/REST/prime_create_transfer.py +++ b/REST/prime_create_transfer.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_wallet.py b/REST/prime_create_wallet.py index 1648894..a1edcdc 100644 --- a/REST/prime_create_wallet.py +++ b/REST/prime_create_wallet.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_wallet_deposit_address.py b/REST/prime_create_wallet_deposit_address.py new file mode 100644 index 0000000..cd57be5 --- /dev/null +++ b/REST/prime_create_wallet_deposit_address.py @@ -0,0 +1,61 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Create a deposit address for a wallet') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--network-id', type=str, required=True, help='Network ID (e.g., base-mainnet, ethereum-mainnet)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/addresses' +timestamp = str(int(time.time())) + +payload = { + 'portfolio_id': PORTFOLIO_ID, + 'network_id': args.network_id +} + +url_path = urlparse(uri).path +message = timestamp + 'POST' + url_path + json.dumps(payload) +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.post(uri, json=payload, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_create_withdrawal.py b/REST/prime_create_withdrawal.py index 99abc85..4c64a2e 100644 --- a/REST/prime_create_withdrawal.py +++ b/REST/prime_create_withdrawal.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_create_withdrawal_to_payment_method.py b/REST/prime_create_withdrawal_to_payment_method.py index 49000ac..21979e2 100644 --- a/REST/prime_create_withdrawal_to_payment_method.py +++ b/REST/prime_create_withdrawal_to_payment_method.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse -import json, hmac, hashlib, time, uuid, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_delete_onchain_address_group.py b/REST/prime_delete_onchain_address_group.py new file mode 100644 index 0000000..cd4a82c --- /dev/null +++ b/REST/prime_delete_onchain_address_group.py @@ -0,0 +1,54 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Delete onchain address group') +parser.add_argument('--address-group-id', type=str, required=True, help='Address group ID to delete') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/onchain_address_group/{args.address_group_id}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'DELETE' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.delete(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_edit_order.py b/REST/prime_edit_order.py new file mode 100644 index 0000000..04da88f --- /dev/null +++ b/REST/prime_edit_order.py @@ -0,0 +1,90 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Edit an existing order (beta)') +parser.add_argument('--order-id', type=str, required=True, help='Order ID to edit') +parser.add_argument('--orig-client-order-id', type=str, required=True, help='Original client order ID') +parser.add_argument('--client-order-id', type=str, help='New client order ID (auto-generated if not provided)') +parser.add_argument('--base-quantity', type=str, help='New base quantity') +parser.add_argument('--quote-value', type=str, help='New quote value') +parser.add_argument('--limit-price', type=str, help='New limit price') +parser.add_argument('--stop-price', type=str, help='New stop price') +parser.add_argument('--expiry-time', type=str, help='New expiry time (ISO 8601 format)') +parser.add_argument('--display-quote-size', type=str, help='New display quote size') +parser.add_argument('--display-base-size', type=str, help='New display base size') + +args = parser.parse_args() + +if not args.base_quantity and not args.quote_value: + parser.error('Either --base-quantity or --quote-value must be provided') + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/orders/{args.order_id}/edit' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'orig_client_order_id': args.orig_client_order_id, + 'client_order_id': args.client_order_id if args.client_order_id else str(uuid.uuid4()) +} + +if args.base_quantity: + payload['base_quantity'] = args.base_quantity +if args.quote_value: + payload['quote_value'] = args.quote_value +if args.limit_price: + payload['limit_price'] = args.limit_price +if args.stop_price: + payload['stop_price'] = args.stop_price +if args.expiry_time: + payload['expiry_time'] = args.expiry_time +if args.display_quote_size: + payload['display_quote_size'] = args.display_quote_size +if args.display_base_size: + payload['display_base_size'] = args.display_base_size + +payload_json = json.dumps(payload) +message = timestamp + 'PUT' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.put(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_activity_by_id.py b/REST/prime_get_activity_by_id.py index ccd726e..f09cb94 100644 --- a/REST/prime_get_activity_by_id.py +++ b/REST/prime_get_activity_by_id.py @@ -11,9 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import sys, json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_allocation_by_id.py b/REST/prime_get_allocation_by_id.py index 8fc9af1..ff031c6 100644 --- a/REST/prime_get_allocation_by_id.py +++ b/REST/prime_get_allocation_by_id.py @@ -11,9 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import sys, json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_commission.py b/REST/prime_get_commission.py index 27a2e42..a0c87ff 100644 --- a/REST/prime_get_commission.py +++ b/REST/prime_get_commission.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_counterparty_id.py b/REST/prime_get_counterparty_id.py new file mode 100644 index 0000000..52e5ede --- /dev/null +++ b/REST/prime_get_counterparty_id.py @@ -0,0 +1,46 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/counterparty' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_cross_margin_overview.py b/REST/prime_get_cross_margin_overview.py new file mode 100644 index 0000000..29ca3af --- /dev/null +++ b/REST/prime_get_cross_margin_overview.py @@ -0,0 +1,46 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/cross_margin' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_entity_activity_by_id.py b/REST/prime_get_entity_activity_by_id.py index 824e43c..4705440 100644 --- a/REST/prime_get_entity_activity_by_id.py +++ b/REST/prime_get_entity_activity_by_id.py @@ -11,9 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import sys, json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_entity_fcm_balance.py b/REST/prime_get_entity_fcm_balance.py new file mode 100644 index 0000000..51705fe --- /dev/null +++ b/REST/prime_get_entity_fcm_balance.py @@ -0,0 +1,47 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/balance_summary' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_entity_payment_method.py b/REST/prime_get_entity_payment_method.py new file mode 100644 index 0000000..42af6f3 --- /dev/null +++ b/REST/prime_get_entity_payment_method.py @@ -0,0 +1,52 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +parser = argparse.ArgumentParser(description='Get details for a specific entity payment method') +parser.add_argument('--payment-method-id', type=str, required=True, help='Payment Method ID') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/payment-methods/{args.payment_method_id}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_entity_positions.py b/REST/prime_get_entity_positions.py new file mode 100644 index 0000000..5f64da0 --- /dev/null +++ b/REST/prime_get_entity_positions.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get entity futures positions') +parser.add_argument('--product-id', type=str, help='Product ID to filter positions') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.product_id: + query_params.append(f'product_id={args.product_id}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/positions' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_fcm_margin_call_details.py b/REST/prime_get_fcm_margin_call_details.py new file mode 100644 index 0000000..0fb612d --- /dev/null +++ b/REST/prime_get_fcm_margin_call_details.py @@ -0,0 +1,47 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/margin_call_details' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_fcm_risk_limits.py b/REST/prime_get_fcm_risk_limits.py new file mode 100644 index 0000000..4663faa --- /dev/null +++ b/REST/prime_get_fcm_risk_limits.py @@ -0,0 +1,47 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/risk_limits' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_interest_accruals.py b/REST/prime_get_interest_accruals.py new file mode 100644 index 0000000..89ab741 --- /dev/null +++ b/REST/prime_get_interest_accruals.py @@ -0,0 +1,67 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from datetime import datetime +from datetime import timedelta +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get interest accruals for a portfolio') +parser.add_argument('--start', type=str, help='Start date (ISO 8601 format, e.g., 2025-05-04T00:00:00Z)') +parser.add_argument('--end', type=str, help='End date (ISO 8601 format, e.g., 2025-05-07T00:00:00Z)') +parser.add_argument('--days', type=int, help='Number of days to look back (alternative to --start/--end)') + +args = parser.parse_args() + +# Determine start and end dates +if args.days: + end_date = datetime.now().isoformat() + 'Z' + start_date = (datetime.now() - timedelta(days=args.days)).isoformat() + 'Z' +elif args.start and args.end: + start_date = args.start + end_date = args.end +else: + parser.error('Either --days or both --start and --end must be provided') + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/accruals?start_date={start_date}&end_date={end_date}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_locate_availability.py b/REST/prime_get_locate_availability.py new file mode 100644 index 0000000..d790722 --- /dev/null +++ b/REST/prime_get_locate_availability.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get locate availability for an entity') +parser.add_argument('--locate-date', type=str, help='Locate date (YYYY-MM-DD)') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.locate_date: + query_params.append(f'locate_date={args.locate_date}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/locates_availability' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_fills.py b/REST/prime_get_margin_information.py similarity index 80% rename from REST/prime_list_fills.py rename to REST/prime_get_margin_information.py index 06809be..4b0a235 100644 --- a/REST/prime_list_fills.py +++ b/REST/prime_get_margin_information.py @@ -1,4 +1,4 @@ -# Copyright 2022-present Coinbase Global, Inc. +# Copyright 2025-present Coinbase Global, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,17 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') -PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') - -start_date = time.strftime("%Y-%m-01T00:00:00Z") +ENTITY_ID = os.environ.get('ENTITY_ID') -uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/fills?start_date={start_date}' +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/margin' url_path = urlparse(uri).path timestamp = str(int(time.time())) message = timestamp + 'GET' + url_path diff --git a/REST/prime_get_net_allocation_by_id.py b/REST/prime_get_net_allocation_by_id.py index 6d56c39..483905e 100644 --- a/REST/prime_get_net_allocation_by_id.py +++ b/REST/prime_get_net_allocation_by_id.py @@ -11,9 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import sys, json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_order_by_id.py b/REST/prime_get_order_by_id.py index 38ae72c..25fe5a2 100644 --- a/REST/prime_get_order_by_id.py +++ b/REST/prime_get_order_by_id.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_order_fills.py b/REST/prime_get_order_fills.py index 420c89d..34bbc60 100644 --- a/REST/prime_get_order_fills.py +++ b/REST/prime_get_order_fills.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests, sys + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_portfolio_buying_power.py b/REST/prime_get_portfolio_buying_power.py new file mode 100644 index 0000000..09362b1 --- /dev/null +++ b/REST/prime_get_portfolio_buying_power.py @@ -0,0 +1,54 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get portfolio buying power for a currency pair') +parser.add_argument('--base', type=str, required=True, help='Base currency (e.g., BTC, ETH)') +parser.add_argument('--quote', type=str, required=True, help='Quote currency (e.g., USD)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/buying_power?base_currency={args.base}"e_currency={args.quote}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_portfolio_by_id.py b/REST/prime_get_portfolio_by_id.py index c3b3e99..f0cbfd7 100644 --- a/REST/prime_get_portfolio_by_id.py +++ b/REST/prime_get_portfolio_by_id.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_portfolio_credit_information.py b/REST/prime_get_portfolio_credit_information.py index 1b1e88a..4b54c37 100644 --- a/REST/prime_get_portfolio_credit_information.py +++ b/REST/prime_get_portfolio_credit_information.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_product_candles.py b/REST/prime_get_product_candles.py new file mode 100644 index 0000000..d1a5b97 --- /dev/null +++ b/REST/prime_get_product_candles.py @@ -0,0 +1,74 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from datetime import datetime +from datetime import timedelta +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get product candles data') +parser.add_argument('--product', type=str, required=True, help='Product ID (e.g., BTC-USD, ETH-USD)') +parser.add_argument('--granularity', type=str, default='ONE_HOUR', + choices=['ONE_MINUTE', 'FIVE_MINUTE', 'FIFTEEN_MINUTE', 'THIRTY_MINUTE', + 'ONE_HOUR', 'TWO_HOUR', 'SIX_HOUR', 'ONE_DAY'], + help='Candle granularity (default: ONE_HOUR)') +parser.add_argument('--start', type=str, help='Start time (ISO 8601 format, e.g., 2024-08-30T00:00:00Z)') +parser.add_argument('--end', type=str, help='End time (ISO 8601 format, e.g., 2025-08-01T00:00:00Z)') +parser.add_argument('--hours', type=int, help='Hours of historical data (alternative to --start/--end)') + +args = parser.parse_args() + +# Determine start and end timestamps +if args.hours: + end_timestamp = datetime.now().isoformat() + 'Z' + start_timestamp = (datetime.now() - timedelta(hours=args.hours)).isoformat() + 'Z' +elif args.start and args.end: + start_timestamp = args.start + end_timestamp = args.end +else: + parser.error('Either --hours or both --start and --end must be provided') + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/candles?product_id={args.product}&granularity={args.granularity}&start_time={start_timestamp}&end_time={end_timestamp}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) + +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_trade_finance_fees.py b/REST/prime_get_trade_finance_fees.py new file mode 100644 index 0000000..94f468a --- /dev/null +++ b/REST/prime_get_trade_finance_fees.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get trade finance tiered pricing fees for an entity') +parser.add_argument('--effective-at', type=str, help='Timestamp for fee pricing (RFC3339 format)') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.effective_at: + query_params.append(f'effective_at={args.effective_at}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/tf_tiered_fees' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_transaction.py b/REST/prime_get_transaction.py index 608ce93..cc12adb 100644 --- a/REST/prime_get_transaction.py +++ b/REST/prime_get_transaction.py @@ -12,8 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests, sys + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_get_wallet_balance.py b/REST/prime_get_wallet_balance.py index b5a6328..128f5a3 100644 --- a/REST/prime_get_wallet_balance.py +++ b/REST/prime_get_wallet_balance.py @@ -12,9 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_wallet_by_id.py b/REST/prime_get_wallet_by_id.py index 333b457..1aa4507 100644 --- a/REST/prime_get_wallet_by_id.py +++ b/REST/prime_get_wallet_by_id.py @@ -12,9 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, uuid, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_wallet_by_name.py b/REST/prime_get_wallet_by_name.py index e889784..facd559 100644 --- a/REST/prime_get_wallet_by_name.py +++ b/REST/prime_get_wallet_by_name.py @@ -12,9 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_wallet_deposit_addresses.py b/REST/prime_get_wallet_deposit_addresses.py new file mode 100644 index 0000000..f5e41b3 --- /dev/null +++ b/REST/prime_get_wallet_deposit_addresses.py @@ -0,0 +1,66 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get deposit addresses for a wallet') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--network-id', type=str, help='Network ID (e.g., base-mainnet, ethereum-mainnet)') +parser.add_argument('--sort', type=str, choices=['ASC', 'DESC'], help='Sort direction (ASC or DESC)') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.network_id: + query_params.append(f'network_id={args.network_id}') +if args.sort: + query_params.append(f'sort_direction={args.sort}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/addresses' +if query_string: + uri += f'?{query_string}' + +timestamp = str(int(time.time())) +url_path = urlparse(uri).path +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_get_wallet_deposit_instructions.py b/REST/prime_get_wallet_deposit_instructions.py index 6a01400..bd7d361 100644 --- a/REST/prime_get_wallet_deposit_instructions.py +++ b/REST/prime_get_wallet_deposit_instructions.py @@ -12,9 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, uuid, os, base64, requests, sys +import base64 +import hashlib +import hmac +import json +import os +import sys +import time +import uuid from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_get_withdrawal_power.py b/REST/prime_get_withdrawal_power.py new file mode 100644 index 0000000..73075df --- /dev/null +++ b/REST/prime_get_withdrawal_power.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Get portfolio withdrawal power') +parser.add_argument('--symbol', type=str, help='Asset symbol to check withdrawal power for (e.g., BTC, USD)') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.symbol: + query_params.append(f'symbol={args.symbol}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/withdrawal_power' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_activities.py b/REST/prime_list_activities.py index f63c2c2..7dd73e2 100644 --- a/REST/prime_list_activities.py +++ b/REST/prime_list_activities.py @@ -12,9 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, uuid, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_list_address_book.py b/REST/prime_list_address_book.py index 940b754..81eaaaa 100644 --- a/REST/prime_list_address_book.py +++ b/REST/prime_list_address_book.py @@ -12,9 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, uuid, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_list_allocations.py b/REST/prime_list_allocations.py index ad6ac90..85bbda2 100644 --- a/REST/prime_list_allocations.py +++ b/REST/prime_list_allocations.py @@ -11,10 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time +from datetime import datetime from urllib.parse import urlparse + +import requests from dateutil.relativedelta import relativedelta -from datetime import datetime API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_assets.py b/REST/prime_list_assets.py index d8ad6ff..f3ce164 100644 --- a/REST/prime_list_assets.py +++ b/REST/prime_list_assets.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_balances.py b/REST/prime_list_balances.py index 97f5ec2..508aee2 100644 --- a/REST/prime_list_balances.py +++ b/REST/prime_list_balances.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_balances_csv.py b/REST/prime_list_balances_csv.py index 9df0f94..363619d 100644 --- a/REST/prime_list_balances_csv.py +++ b/REST/prime_list_balances_csv.py @@ -11,9 +11,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import base64 import csv +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_entity_accruals.py b/REST/prime_list_entity_accruals.py new file mode 100644 index 0000000..a16cd62 --- /dev/null +++ b/REST/prime_list_entity_accruals.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List interest accruals for an entity') +parser.add_argument('--portfolio-id', type=str, required=True, help='The unique ID of the portfolio') +parser.add_argument('--start-date', type=str, required=True, help='Start date in RFC3339 format') +parser.add_argument('--end-date', type=str, required=True, help='End date in RFC3339 format') + +args = parser.parse_args() + +# Build query string +query_params = [ + f'portfolio_id={args.portfolio_id}', + f'start_date={args.start_date}', + f'end_date={args.end_date}' +] + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/accruals?{"&".join(query_params)}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_entity_activities.py b/REST/prime_list_entity_activities.py index 90fbafd..0ce7dff 100644 --- a/REST/prime_list_entity_activities.py +++ b/REST/prime_list_entity_activities.py @@ -12,9 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, hmac, hashlib, time, os, base64, requests +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse +import requests + API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') PASSPHRASE = os.environ.get('PASSPHRASE') diff --git a/REST/prime_list_entity_balances.py b/REST/prime_list_entity_balances.py new file mode 100644 index 0000000..4dad592 --- /dev/null +++ b/REST/prime_list_entity_balances.py @@ -0,0 +1,45 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/balances' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_entity_futures_sweeps.py b/REST/prime_list_entity_futures_sweeps.py new file mode 100644 index 0000000..0ffd580 --- /dev/null +++ b/REST/prime_list_entity_futures_sweeps.py @@ -0,0 +1,46 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/sweeps' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_entity_payment_methods.py b/REST/prime_list_entity_payment_methods.py index 71b2db6..ae6b47b 100644 --- a/REST/prime_list_entity_payment_methods.py +++ b/REST/prime_list_entity_payment_methods.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_invoices.py b/REST/prime_list_invoices.py index d2c4e04..defca3d 100644 --- a/REST/prime_list_invoices.py +++ b/REST/prime_list_invoices.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_locates.py b/REST/prime_list_locates.py new file mode 100644 index 0000000..8a9968f --- /dev/null +++ b/REST/prime_list_locates.py @@ -0,0 +1,65 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List existing locates for a portfolio') +parser.add_argument('--locate-date', type=str, help='Filter by locate date (YYYY-MM-DD)') +parser.add_argument('--locate-ids', type=str, help='Comma-separated list of locate IDs to filter') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.locate_date: + query_params.append(f'locate_date={args.locate_date}') +if args.locate_ids: + query_params.append(f'locate_ids={args.locate_ids}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/locates' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_margin_call_summaries.py b/REST/prime_list_margin_call_summaries.py new file mode 100644 index 0000000..1ed8bbe --- /dev/null +++ b/REST/prime_list_margin_call_summaries.py @@ -0,0 +1,64 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List margin call summaries for an entity') +parser.add_argument('--start-date', type=str, help='Start date in RFC3339 format (must be within last 3 months)') +parser.add_argument('--end-date', type=str, help='End date in RFC3339 format') + +args = parser.parse_args() + +# Build query string +query_params = [] +if args.start_date: + query_params.append(f'start_date={args.start_date}') +if args.end_date: + query_params.append(f'end_date={args.end_date}') + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/margin_summaries' +if query_params: + uri += f'?{"&".join(query_params)}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_onchain_address_groups.py b/REST/prime_list_onchain_address_groups.py new file mode 100644 index 0000000..80ae94e --- /dev/null +++ b/REST/prime_list_onchain_address_groups.py @@ -0,0 +1,48 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/onchain_address_groups' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_onchain_wallet_balances.py b/REST/prime_list_onchain_wallet_balances.py new file mode 100644 index 0000000..e5a0616 --- /dev/null +++ b/REST/prime_list_onchain_wallet_balances.py @@ -0,0 +1,63 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List onchain wallet balances including DeFi positions') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--visibility', type=str, help='Filter by visibility status') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = [] +if args.visibility: + query_params.append(f'visibility_statuses={args.visibility}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/web3_balances' +if query_string: + uri += f'?{query_string}' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_open_orders.py b/REST/prime_list_open_orders.py index 86f2587..6c4bdfa 100644 --- a/REST/prime_list_open_orders.py +++ b/REST/prime_list_open_orders.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_order_fills.py b/REST/prime_list_order_fills.py new file mode 100644 index 0000000..6b6c47d --- /dev/null +++ b/REST/prime_list_order_fills.py @@ -0,0 +1,54 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List fills for a specific order') +parser.add_argument('--order-id', type=str, required=True, help='Order ID') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/orders/{args.order_id}/fills' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_orders.py b/REST/prime_list_orders.py index d9aa72e..1905043 100644 --- a/REST/prime_list_orders.py +++ b/REST/prime_list_orders.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_payment_methods.py b/REST/prime_list_payment_methods.py index c24ba37..384352a 100644 --- a/REST/prime_list_payment_methods.py +++ b/REST/prime_list_payment_methods.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_portfolio_fills.py b/REST/prime_list_portfolio_fills.py new file mode 100644 index 0000000..4bac0da --- /dev/null +++ b/REST/prime_list_portfolio_fills.py @@ -0,0 +1,61 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from datetime import datetime +from datetime import timedelta +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +parser = argparse.ArgumentParser(description='List portfolio fills') +parser.add_argument('--start', type=str, required=True, help='Start date (ISO 8601 format, e.g., 2025-01-01T00:00:00Z)') +parser.add_argument('--end', type=str, help='End date (ISO 8601 format, e.g., 2025-01-31T23:59:59Z) - optional') + +args = parser.parse_args() + +# Build query parameters +query_params = [f'start_date={args.start}'] +if args.end: + query_params.append(f'end_date={args.end}') + +query_string = '&'.join(query_params) +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/fills?{query_string}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_portfolios.py b/REST/prime_list_portfolios.py index cc16d27..9122a59 100644 --- a/REST/prime_list_portfolios.py +++ b/REST/prime_list_portfolios.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_products.py b/REST/prime_list_products.py index a5ae164..9524fb3 100644 --- a/REST/prime_list_products.py +++ b/REST/prime_list_products.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_transaction_validators.py b/REST/prime_list_transaction_validators.py new file mode 100644 index 0000000..0f5b95d --- /dev/null +++ b/REST/prime_list_transaction_validators.py @@ -0,0 +1,61 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List transaction validators') +parser.add_argument('--transaction-ids', type=str, required=True, help='Comma-separated list of transaction IDs') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/staking/transaction-validators/query' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'transaction_ids': args.transaction_ids.split(',') +} + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_transactions.py b/REST/prime_list_transactions.py index 83b9bd8..245c72c 100644 --- a/REST/prime_list_transactions.py +++ b/REST/prime_list_transactions.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_list_transactions_csv.py b/REST/prime_list_transactions_csv.py new file mode 100644 index 0000000..cdc79eb --- /dev/null +++ b/REST/prime_list_transactions_csv.py @@ -0,0 +1,85 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import base64 +import csv +import hashlib +import hmac +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') +BASE_URI = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/transactions' + +def get_signature(timestamp, method, path): + message = timestamp + method + path + return base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +def get_headers(path, timestamp): + return { + 'X-CB-ACCESS-SIGNATURE': get_signature(timestamp, 'GET', path), + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' + } + +def fetch_transactions(): + all_transactions = [] + next_cursor = None + + while True: + uri = BASE_URI + if next_cursor: + uri += f"?cursor={next_cursor}" + + path = urlparse(BASE_URI).path + timestamp = str(int(time.time())) + headers = get_headers(path, timestamp) + + response = requests.get(uri, headers=headers) + if response.status_code != 200: + raise Exception(f"Failed to fetch: {response.text}") + + data = response.json() + transactions = data.get("transactions", []) + all_transactions.extend(transactions) + + pagination = data.get("pagination", {}) + next_cursor = pagination.get("next_cursor") + if not pagination.get("has_next"): + break + + return all_transactions + +def write_to_csv(transactions, filename="transactions.csv"): + if not transactions: + print("No transactions to write.") + return + + with open(filename, mode='w', newline='') as csvfile: + writer = csv.DictWriter(csvfile, fieldnames=transactions[0].keys()) + writer.writeheader() + for tx in transactions: + writer.writerow(tx) + +if __name__ == "__main__": + txs = fetch_transactions() + write_to_csv(txs) + print(f"Exported {len(txs)} transactions to transactions.csv") diff --git a/REST/prime_list_wallet_transactions.py b/REST/prime_list_wallet_transactions.py new file mode 100644 index 0000000..6f66793 --- /dev/null +++ b/REST/prime_list_wallet_transactions.py @@ -0,0 +1,60 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='List wallet transactions') +parser.add_argument('--wallet-id', type=str, required=True, help='Wallet ID') +parser.add_argument('--types', type=str, help='Transaction types (comma-separated, e.g., DEPOSIT,WITHDRAWAL)') +parser.add_argument('--limit', type=int, default=100, help='Maximum number of transactions to return (default: 100)') + +args = parser.parse_args() + +# Build URI with query parameters +query_params = f'limit={args.limit}' +if args.types: + query_params += f'&types={args.types}' + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/wallets/{args.wallet_id}/transactions?{query_params}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_list_wallets.py b/REST/prime_list_wallets.py index 8e98c00..345bc68 100644 --- a/REST/prime_list_wallets.py +++ b/REST/prime_list_wallets.py @@ -12,8 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import hashlib +import hmac +import json +import os +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests + +import requests API_KEY = os.environ.get('ACCESS_KEY') SECRET_KEY = os.environ.get('SIGNING_KEY') diff --git a/REST/prime_locate_order_by_client_order_id.py b/REST/prime_locate_order_by_client_order_id.py index 2d98925..990898a 100644 --- a/REST/prime_locate_order_by_client_order_id.py +++ b/REST/prime_locate_order_by_client_order_id.py @@ -1,5 +1,13 @@ +import base64 +import hashlib +import hmac +import json +import os +import sys +import time from urllib.parse import urlparse -import json, hmac, hashlib, time, os, base64, requests, sys + +import requests if len(sys.argv) < 2: print('Usage: python prime_locate_order_by_client_order_id.py ') diff --git a/REST/prime_plot_product_candles.py b/REST/prime_plot_product_candles.py new file mode 100644 index 0000000..cb6830e --- /dev/null +++ b/REST/prime_plot_product_candles.py @@ -0,0 +1,103 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from datetime import datetime +from datetime import timedelta +from urllib.parse import urlparse + +import matplotlib.dates as mdates +import matplotlib.pyplot as plt +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Plot candlestick chart for a product') +parser.add_argument('--product', type=str, required=True, help='Product ID (e.g., BTC-USD, ETH-USD)') +parser.add_argument('--granularity', type=str, default='ONE_HOUR', + choices=['ONE_MINUTE', 'FIVE_MINUTE', 'FIFTEEN_MINUTE', 'THIRTY_MINUTE', + 'ONE_HOUR', 'TWO_HOUR', 'SIX_HOUR', 'ONE_DAY'], + help='Candle granularity (default: ONE_HOUR)') +parser.add_argument('--hours', type=int, default=350, help='Hours of historical data to fetch (default: 350)') + +args = parser.parse_args() + +end_time = datetime.now() +start_time = end_time - timedelta(hours=args.hours) +end_timestamp = int(end_time.timestamp()) +start_timestamp = int(start_time.timestamp()) + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/candles?product_id={args.product}&granularity={args.granularity}&start_time={start_timestamp}&end_time={end_timestamp}' +url_path = urlparse(uri).path +timestamp = str(int(time.time())) +message = timestamp + 'GET' + url_path +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json' +} + +response = requests.get(uri, headers=headers) +parsed_response = json.loads(response.text) + +if 'candles' in parsed_response: + candles = parsed_response['candles'] + + timestamps = [datetime.fromisoformat(candle['timestamp'].replace('Z', '+00:00')) for candle in candles] + opens = [float(candle['open']) for candle in candles] + highs = [float(candle['high']) for candle in candles] + lows = [float(candle['low']) for candle in candles] + closes = [float(candle['close']) for candle in candles] + + fig, ax = plt.subplots(figsize=(12, 8)) + + for i in range(len(timestamps)): + color = 'green' if closes[i] >= opens[i] else 'red' + + ax.plot([timestamps[i], timestamps[i]], [lows[i], highs[i]], color='black', linewidth=1) + + body_height = abs(closes[i] - opens[i]) + body_bottom = min(opens[i], closes[i]) + + ax.bar(timestamps[i], body_height, bottom=body_bottom, width=0.8/24, + color=color, alpha=0.7, edgecolor='black', linewidth=0.5) + + ax.set_title(f'{args.product} Candlestick Chart ({args.granularity})', fontsize=16) + ax.set_xlabel('Time', fontsize=12) + ax.set_ylabel('Price (USD)', fontsize=12) + + ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d %H:%M')) + ax.xaxis.set_major_locator(mdates.HourLocator(interval=6)) + plt.xticks(rotation=45) + + plt.tight_layout() + plt.grid(True, alpha=0.3) + plt.show() +else: + print("Error: No candles data in response") + print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_request_portfolio_stake.py b/REST/prime_request_portfolio_stake.py new file mode 100644 index 0000000..3ba1e31 --- /dev/null +++ b/REST/prime_request_portfolio_stake.py @@ -0,0 +1,71 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Request to stake currency in a portfolio') +parser.add_argument('--currency-symbol', type=str, required=True, help='Currency symbol to stake (e.g., ETH)') +parser.add_argument('--amount', type=str, required=True, help='Quantity to stake') +parser.add_argument('--external-id', type=str, help='Custom identifier (up to 255 characters)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/staking/initiate' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'idempotency_key': str(uuid.uuid4()), + 'currency_symbol': args.currency_symbol, + 'amount': args.amount +} + +if args.external_id: + payload['metadata'] = { + 'external_id': args.external_id + } + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_request_portfolio_unstake.py b/REST/prime_request_portfolio_unstake.py new file mode 100644 index 0000000..f6700e6 --- /dev/null +++ b/REST/prime_request_portfolio_unstake.py @@ -0,0 +1,71 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +import uuid +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Request to unstake currency across a portfolio') +parser.add_argument('--currency-symbol', type=str, required=True, help='Currency symbol to unstake (e.g., ETH)') +parser.add_argument('--amount', type=str, required=True, help='Quantity to unstake') +parser.add_argument('--external-id', type=str, help='Custom identifier (up to 255 characters)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/staking/unstake' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'idempotency_key': str(uuid.uuid4()), + 'currency_symbol': args.currency_symbol, + 'amount': args.amount +} + +if args.external_id: + payload['metadata'] = { + 'external_id': args.external_id + } + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_schedule_entity_futures_sweep.py b/REST/prime_schedule_entity_futures_sweep.py new file mode 100644 index 0000000..52cb1af --- /dev/null +++ b/REST/prime_schedule_entity_futures_sweep.py @@ -0,0 +1,64 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +parser = argparse.ArgumentParser(description='Schedule entity futures sweep from FCM wallet to USD Spot wallet') +parser.add_argument('--currency', type=str, required=True, help='Currency symbol (e.g. USD)') +parser.add_argument('--amount', type=str, help='Amount to sweep (optional - defaults to sweep all if not provided)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/sweeps' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +payload = { + 'currency': args.currency +} + +if args.amount: + payload['amount'] = args.amount + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_set_auto_sweep.py b/REST/prime_set_auto_sweep.py new file mode 100644 index 0000000..1bf7dca --- /dev/null +++ b/REST/prime_set_auto_sweep.py @@ -0,0 +1,62 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +ENTITY_ID = os.environ.get('ENTITY_ID') + +parser = argparse.ArgumentParser(description='Set auto sweep configuration') +parser.add_argument('--auto-sweep', type=str, required=True, choices=['true', 'false'], help='Enable or disable auto sweep') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/entities/{ENTITY_ID}/futures/auto_sweep' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +auto_sweep_bool = args.auto_sweep.lower() == 'true' + +payload = { + 'auto_sweep': auto_sweep_bool +} + +payload_json = json.dumps(payload) +message = timestamp + 'POST' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.post(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_update_onchain_address_book_entry.py b/REST/prime_update_onchain_address_book_entry.py new file mode 100644 index 0000000..a19f580 --- /dev/null +++ b/REST/prime_update_onchain_address_book_entry.py @@ -0,0 +1,77 @@ +# Copyright 2025-present Coinbase Global, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import base64 +import hashlib +import hmac +import json +import os +import time +from urllib.parse import urlparse + +import requests + +API_KEY = os.environ.get('ACCESS_KEY') +SECRET_KEY = os.environ.get('SIGNING_KEY') +PASSPHRASE = os.environ.get('PASSPHRASE') +PORTFOLIO_ID = os.environ.get('PORTFOLIO_ID') + +# Parse command line arguments +parser = argparse.ArgumentParser(description='Update onchain address group') +parser.add_argument('--group-id', type=str, required=True, help='Address group ID') +parser.add_argument('--name', type=str, required=True, help='Group name') +parser.add_argument('--network-type', type=str, required=True, choices=['NETWORK_TYPE_EVM', 'NETWORK_TYPE_SOLANA'], help='Network type') +parser.add_argument('--addresses', type=str, required=True, help='JSON array of address entries') +parser.add_argument('--added-at', type=str, required=True, help='Added at timestamp (ISO 8601 format)') + +args = parser.parse_args() + +uri = f'https://api.prime.coinbase.com/v1/portfolios/{PORTFOLIO_ID}/onchain_address_group' + +url_path = urlparse(uri).path +timestamp = str(int(time.time())) + +# Parse addresses JSON +try: + addresses = json.loads(args.addresses) +except json.JSONDecodeError: + parser.error('--addresses must be valid JSON array') + +payload = { + 'address_group': { + 'id': args.group_id, + 'name': args.name, + 'network_type': args.network_type, + 'addresses': addresses, + 'added_at': args.added_at + } +} + +payload_json = json.dumps(payload) +message = timestamp + 'PUT' + url_path + payload_json +signature_b64 = base64.b64encode(hmac.digest(SECRET_KEY.encode(), message.encode(), hashlib.sha256)) + +headers = { + 'X-CB-ACCESS-SIGNATURE': signature_b64, + 'X-CB-ACCESS-TIMESTAMP': timestamp, + 'X-CB-ACCESS-KEY': API_KEY, + 'X-CB-ACCESS-PASSPHRASE': PASSPHRASE, + 'Accept': 'application/json', + 'Content-Type': 'application/json' +} + +response = requests.put(uri, headers=headers, data=payload_json) +parsed_response = json.loads(response.text) +print(json.dumps(parsed_response, indent=3)) diff --git a/REST/prime_ws_heartbeats.py b/REST/prime_ws_heartbeats.py index e8f88ef..f8e36a0 100644 --- a/REST/prime_ws_heartbeats.py +++ b/REST/prime_ws_heartbeats.py @@ -12,7 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import asyncio, base64, hashlib, hmac, json, os, sys, time, websockets +import asyncio +import base64 +import hashlib +import hmac +import json +import os +import sys +import time + +import websockets PASSPHRASE = os.environ.get('PASSPHRASE') ACCESS_KEY = os.environ.get('ACCESS_KEY') diff --git a/REST/prime_ws_market.py b/REST/prime_ws_market.py index bfe8cf6..5acf689 100644 --- a/REST/prime_ws_market.py +++ b/REST/prime_ws_market.py @@ -12,7 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import asyncio, base64, hashlib, hmac, json, os, sys, time, websockets +import asyncio +import base64 +import hashlib +import hmac +import json +import os +import sys +import time + +import websockets PASSPHRASE = os.environ.get('PASSPHRASE') ACCESS_KEY = os.environ.get('ACCESS_KEY') @@ -20,19 +29,24 @@ SVC_ACCOUNTID = os.environ.get('SVC_ACCOUNTID') uri = 'wss://ws-feed.prime.coinbase.com' -timestamp = str(int(time.time())) -channel = 'l2_data' -product_ids = ['ETH-USD'] +product_ids = ['BTC-USD'] + + +def sign(channel: str, key: str, account_id: str, product_ids: list, timestamp: str) -> str: + message = channel + key + account_id + timestamp + "".join(product_ids) + signature = hmac.new(SECRET_KEY.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).digest() + return base64.b64encode(signature).decode() async def main_loop(): - while True: - try: - async with websockets.connect(uri, ping_interval=None, max_size=None) as websocket: - signature = sign(channel, ACCESS_KEY, SVC_ACCOUNTID, product_ids) + try: + async with websockets.connect(uri, ping_interval=None, max_size=None) as websocket: + for ch in ['l2_data', 'heartbeats']: + timestamp = str(int(time.time())) + signature = sign(ch, ACCESS_KEY, SVC_ACCOUNTID, product_ids, timestamp) auth_message = json.dumps({ 'type': 'subscribe', - 'channel': channel, + 'channel': ch, 'access_key': ACCESS_KEY, 'api_key_id': SVC_ACCOUNTID, 'timestamp': timestamp, @@ -41,23 +55,21 @@ async def main_loop(): 'product_ids': product_ids }) await websocket.send(auth_message) - while True: - response = await websocket.recv() - parsed_response = json.loads(response) - print(json.dumps(parsed_response, indent=3)) - except websockets.ConnectionClosed: - continue + while True: + response = await websocket.recv() + parsed_response = json.loads(response) -def sign(channel, key, account_id, product_ids): - message = channel + key + account_id + timestamp + "".join(product_ids) - signature = hmac.new(SECRET_KEY.encode('utf-8'), message.encode('utf-8'), digestmod=hashlib.sha256).digest() - signature_b64 = base64.b64encode(signature).decode() - return signature_b64 + if parsed_response.get("type") == "snapshot": + continue + + print(json.dumps(parsed_response, indent=3)) + except websockets.ConnectionClosed: + print("Connection closed, exiting...") + except KeyboardInterrupt: + print("\nInterrupted, exiting...") + sys.exit() -try: +if __name__ == "__main__": asyncio.get_event_loop().run_until_complete(main_loop()) -except KeyboardInterrupt: - print('\nClosing Prime websocket feed') - sys.exit() diff --git a/REST/prime_ws_orders.py b/REST/prime_ws_orders.py index e5862b3..53cbbbb 100644 --- a/REST/prime_ws_orders.py +++ b/REST/prime_ws_orders.py @@ -12,7 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import asyncio, base64, hashlib, hmac, json, os, sys, time, websockets +import asyncio +import base64 +import hashlib +import hmac +import json +import os +import sys +import time + +import websockets PASSPHRASE = os.environ.get('PASSPHRASE') ACCESS_KEY = os.environ.get('ACCESS_KEY') diff --git a/REST/requirements.txt b/REST/requirements.txt index aef21a8..f6c139a 100644 --- a/REST/requirements.txt +++ b/REST/requirements.txt @@ -1,2 +1,2 @@ -websockets==11.0.3 -requests==2.32.4 +websockets>=13.1 +requests>=2.32.4 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2162a10 --- /dev/null +++ b/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup( + name="prime-scripts-py", + version="1.0.0" +)