Skip to content

How can I use ClearScript to call Node.js script with NPM and possibly pass some parameter? #435

Closed

Description

@zydjohnHotmail

Hello:
I want to know if I can find how can I call some Node.js script from C#, which call a npm package called ccxt, and return the truncated strings to C#. And one step further, how can I call similar Node.js script and pass some parameter and get the results back to C#.
My OS: Window 10 Pro (version 21H2)
Node.js: version: 18.10.0
CCXT: version: 2.0.79

The following is node.js script:
D:\nodejs\CCXT_Exchanges>type ccxt_all_exchanges.js
'use strict';
const ccxt = require('ccxt');
console.log(ccxt.version);
var all_exchanges = ccxt.exchanges
console.log(all_exchanges)
D:\nodejs\CCXT_Exchanges>
The output for running the node.js script:
D:\nodejs\CCXT_Exchanges>node ccxt_all_exchanges.js
2.0.79
[
'aax', 'alpaca', 'ascendex',
'bequant', 'bibox', 'bigone',
'binance', 'binancecoinm', 'binanceus',
'binanceusdm', 'bit2c', 'bitbank',
'bitbay', 'bitbns', 'bitcoincom',
'bitfinex', 'bitfinex2', 'bitflyer',
'bitforex', 'bitget', 'bithumb',
'bitmart', 'bitmex', 'bitopro',
'bitpanda', 'bitrue', 'bitso',
'bitstamp', 'bitstamp1', 'bittrex',
'bitvavo', 'bkex', 'bl3p',
'blockchaincom', 'btcalpha', 'btcbox',
'btcex', 'btcmarkets', 'btctradeua',
'btcturk', 'buda', 'bw',
'bybit', 'bytetrade', 'cex',
'coinbase', 'coinbaseprime', 'coinbasepro',
'coincheck', 'coinex', 'coinfalcon',
'coinmate', 'coinone', 'coinspot',
'crex24', 'cryptocom', 'currencycom',
'delta', 'deribit', 'digifinex',
'exmo', 'flowbtc', 'fmfwio',
'ftx', 'ftxus', 'gate',
'gateio', 'gemini', 'hitbtc',
'hitbtc3', 'hollaex', 'huobi',
'huobijp', 'huobipro', 'idex',
'independentreserve', 'indodax', 'itbit',
'kraken', 'kucoin', 'kucoinfutures',
'kuna', 'latoken', 'lbank',
'lbank2', 'liquid', 'luno',
'lykke', 'mercado', 'mexc',
'mexc3', 'ndax', 'novadax',
'oceanex', 'okcoin', 'okex',
'okex5', 'okx', 'paymium',
'phemex',
... 20 more items
]

D:\nodejs\CCXT_Exchanges>
The issue here is that console.log only shows the first 100 items, there are 20 more items will be returned. I want to use ClearScript to run the above node.js script and return all 120 items to C#.
How can I do this?

One step further:
I modified the above node.js script to add one parameter, so the script will return detailed information about only one exchange from total 120 exchanges.
D:\nodejs\CCXT_Exchanges>type ccxt_get1_exchange.js
'use strict';
const ccxt = require('ccxt');
console.log(ccxt.version);

const [nodejs, script1, exchange1] = process.argv;
let exchange = new ccxt[exchange1];
console.log(exchange)

D:\nodejs\CCXT_Exchanges>
To use this script, add one exchange name as show from the first node.js, like the following:
D:\nodejs\CCXT_Exchanges>node ccxt_get1_exchange.js aax
2.0.79
aax {
isBrowser: false,
…..
A lot of output, here are ignored.

I want to know how I can call the node.js script and pass one parameter, like: aax, and get the result, a very long string, back to C#.
I am using Visual Studio 2022, version 17.3.6; I can install NUGET package for ClearScript version 7.3.4.
Please advise on how can I write some C# code in Console program or in WinForms project for this job.
Thanks,

Activity

  1. ClearScriptLib commented on Oct 28, 2022

    @ClearScriptLib
    Collaborator

    Hi @zydjohnHotmail,

    ClearScript only provides a standard JavaScript environment. It implements neither the Web APIs nor the Node.js API. The idea is that you start with the bare standard and use .NET to provide whatever APIs your script code requires.

    However, the CCXT code doesn't seem to have too many external dependencies, at least when it comes to executing its main script. In fact, loading the web version of CCXT is quite easy:

    using var engine = new V8ScriptEngine();
    engine.Execute("self = this; setTimeout = () => {}");
    engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableWebLoading;
    engine.ExecuteDocument("https://cdn.jsdelivr.net/npm/ccxt@2.0.79/dist/ccxt.browser.js");

    Once you've done that, the .NET host and the script engine can work together to access the data:

    engine.AddHostType(typeof(Console));
    engine.Execute(@"
        function dumpExchangeNames() {
            for (let exchange of ccxt.exchanges) {
                Console.WriteLine(exchange);
            }
        }
        function dumpExchange(name) {
            const exchange = new ccxt[name]();
            Console.WriteLine(name + ': ' + JSON.stringify(exchange, undefined, 4));
        }
    ");
    engine.Script.dumpExchangeNames();
    engine.Script.dumpExchange("bitflyer");
    engine.Script.dumpExchange("coinbase");
    // etc.

    It does look like some other CCXT capabilities require additional APIs – e.g., fetch – so if you need that functionality, you'll have to expose a fetch implementation yourself.

    Good luck!

  2. zydjohnHotmail commented on Oct 28, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thank you very much for your code and explanation. I have only one minor issue, most of the time, I will call CCXT Node.js script from a WinForms project, as I can have many different tasks assigned to different button click, so each button will do specific job. For example, button1 will call CCXT to get exchange AAX, and button2 will call CCXT to get exchange Binance.
    How can I return the result as one long string, and in C# code, I can use newtonsoft to parse the Json format string, I don't want just see the results appear on the console window.
    Please advise,
    Thank you very much!

  3. ClearScriptLib commented on Oct 29, 2022

    @ClearScriptLib
    Collaborator

    HI @zydjohnHotmail,

    How can I return the result as one long string, and in C# code, I can use newtonsoft to parse the Json format string

    No problem at all:

    engine.Execute(@"
        function getExchangeJSON(name) {
            const exchange = new ccxt[name]();
            return JSON.stringify(exchange);
        }
    ");
    string json = engine.Script.getExchangeJSON("coinbase");
    var exchange = JObject.Parse(json);
    Console.WriteLine("{0} {1}", exchange["name"], exchange["version"]);
    Console.WriteLine(exchange["requiredCredentials"]);
    // etc.

    Cheers!

  4. zydjohnHotmail commented on Oct 29, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thank you very much for your code and help.
    Now I have one further question: how can I write some async function in ClearScript?
    For example, I have to following Node.JS which can get the account balance for one exchange: Binance, I skip the API and secret key for personal data:

    'use strict';
    const ccxt = require ('ccxt');

    (async function () {
    let binance = new ccxt.binance ({
    apiKey: 'My_API_Key',
    secret: 'My_Scret_Key',
    })
    console.log(await binance.fetchBalance())
    }) ();

    I have the following C# code in ClearScript:
    using V8ScriptEngine engine = new();
    engine.Execute("self = this; setTimeout = () => {}");
    engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableWebLoading;
    engine.ExecuteDocument(CCXT_JS_Web_Loader_Url);
    engine.Execute(@"
    function getExchange1Balance(name, key0, key1) {
    const exchange = new ccxt[name]({
    apiKey: 'key0',
    secret: 'key1',});
    const balance = await exchange.fetchBalance()
    return JSON.stringify(balance);
    }
    ");
    string json_data =
    engine.Script.getExchange1Balance("binance", API_Key, Secret_Key);
    var json_balance = JObject.Parse(json_data);

    When I run this, I got the following error, which is logic:
    System.Reflection.TargetInvocationException
    HResult=0x80131604
    Message=Exception has been thrown by the target of an invocation.
    Source=System.Private.CoreLib
    StackTrace:
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at System.Delegate.DynamicInvokeImpl(Object[] args)
    at System.Delegate.DynamicInvoke(Object[] args)
    at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
    at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
    --- End of stack trace from previous location ---
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
    at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, WM msg, IntPtr wparam, IntPtr lparam)
    at Interop.User32.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.Interop.Mso.IMsoComponentManager.FPushMessageLoop(UIntPtr dwComponentID, msoloop uReason, Void* pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(msoloop reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(msoloop reason, ApplicationContext context)
    at System.Windows.Forms.Application.Run(Form mainForm)
    at CCXTAccount1BalanceForm.Program.Main() in C:\ArbitApps\ClearScriptCCXT\CCXTAccount1BalanceForm\CCXTAccount1BalanceForm\Program.cs:line 14

    This exception was originally thrown at this call stack:
    Microsoft.ClearScript.V8.SplitProxy.V8SplitProxyNative.Invoke(System.Func<Microsoft.ClearScript.V8.SplitProxy.IV8SplitProxyNative, T>)
    Microsoft.ClearScript.V8.V8ScriptEngine.ExecuteInternal(Microsoft.ClearScript.UniqueDocumentInfo, string, bool)
    Microsoft.ClearScript.V8.V8ScriptEngine.Execute.AnonymousMethod__0()
    Microsoft.ClearScript.ScriptEngine.ScriptInvokeInternal(System.Func)
    Microsoft.ClearScript.V8.V8ScriptEngine.ScriptInvoke.AnonymousMethod__0()
    Microsoft.ClearScript.V8.SplitProxy.V8SplitProxyManaged.InvokeHostAction(System.IntPtr)

    Inner Exception 1:
    ScriptEngineException: SyntaxError: await is only valid in async functions and the top level bodies of modules

    Inner Exception 2:
    ScriptEngineException: SyntaxError: await is only valid in async functions and the top level bodies of modules

    I don’t know how to write async functions in ClearScript, and how to pass the API_key, Secre_Key, please advise! I also prefer a named function, like: GetBalance.
    Thanks,

  5. ClearScriptLib commented on Oct 30, 2022

    @ClearScriptLib
    Collaborator

    Hi @zydjohnHotmail,

    I don’t know how to write async functions in ClearScript

    It is the script engine – not ClearScript – that defines the supported language features. Luckily, V8 complies with the latest JavaScript standards, so it has full support for async functions.

    and how to pass the API_key, Secre_Key

    Here's a quick sample that demonstrates JavaScript async functions, passing arguments from the host, and ClearScript's support for promise-task interoperability:

    public static async Task Main() {
        using (var engine = new V8ScriptEngine(V8ScriptEngineFlags.EnableTaskPromiseConversion)) {
            engine.Script.delay = new Func<int, Task>(Task.Delay);
            engine.AddHostType(typeof(Console));
            engine.Execute(@"
                async function repeatWithDelay(message, count, ms) {
                    for (let i = 0; i < count; ++i) {
                        await delay(ms);
                        Console.WriteLine(message);
                    }
                }
            ");
            await engine.Script.repeatWithDelay("Hello!", 5, 1000);
        }
    }

    As for the fetchBalance method you're trying to call, we played with it briefly. As suspected, fetchBalance depends on a few more non-standard APIs that ClearScript doesn't provide. The most significant of these is fetch, so you'll have to implement that yourself, perhaps with the help of .NET's HttClient class.

    Good luck!

  6. zydjohnHotmail commented on Oct 30, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thank you very much for your code. I think may it is possible since CCXT has the source code we can use, if I spend enough time to figure out how CCXT implement fetch, then use the fetch with plain JavaScript in ClearScript, this should work, right?
    Please advise on my idea.
    By the way, I have another example to use CCXT aync function, but without personal keys.
    The following is the description:
    D:\nodejs\CCXT_Markets>type ccxt_exchange1_markets.js
    'use strict';
    const ccxt = require('ccxt');
    console.log(ccxt.version);
    const [nodejs, script1, exchange1, ticker1] = process.argv;

    (async function ()
    {
    let exchange = new ccxt[exchange1];
    await exchange.loadMarkets();
    console.log(exchange.id);
    let ticker_data = await exchange.fetchTicker(ticker1);
    console.log (ticker_data)
    }) ();

    To use the script, pass 2 parameters, one is exchange name, as appeared in the first script, pick any one from the 120 items shown above; the second parameter is one crypto-currency name, like: BTC/USDT.
    The following is one example how to use the Node.JS code:
    D:\nodejs\CCXT_Markets>node ccxt_exchange1_markets.js binance BTC/USDT
    Let me know if you can use ClearScript to call this Node script with too much efforts.
    Thanks,

  7. ClearScriptLib commented on Oct 30, 2022

    @ClearScriptLib
    Collaborator

    hi @zydjohnHotmail,

    if I spend enough time to figure out how CCXT implement fetch, then use the fetch with plain JavaScript in ClearScript, this should work, right?
    Please advise on my idea.

    Since standard JavaScript has no I/O facilities, a script can't implement fetch without help from the host. Luckily, .NET provides tons of support for web requests, so it shouldn't be too difficult to implement fetch on top of HttpClient or something similar.

    Let me know if you can use ClearScript to call this Node script with too much efforts.

    That script uses several non-standard facilities: console, process, and whatever fetchTicker depends on, which probably includes fetch, setTimeout, and clearTimeout.

    Instead of using process.argv, your script could have the async function declare exchange1 and ticker1 as parameters, and we've already demonstrated how to pass arguments from the host. As for console, you could easily use .NET's Console class to implement the required subset. You'll also need proper implementations of setTimeout, clearTimeout, and fetch. Since we haven't been able to test beyond that, we don't know whether CCXT uses additional non-standard facilities.

    Cheers!

  8. zydjohnHotmail commented on Oct 30, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thanks for your code, I am now trying to use a simple way, which many other people told me it works.
    I simply run a CMD command line to launch node program and pass parameter, to make it simple, I simply use the first node.js script, which shows all the exchanges CCXT has now.
    The following is my C# code:
    Process p = new();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT_Exchanges\ccxt_all_exchanges.js";
    p.Start();
    p.WaitForExit();

    I can run this code, however, it seems impossible to see any output from the CCXT node.js script. The process window just show less than 1 second, and it disappears, no time to see the output, which should show 100 exchanges CCXT supports.
    I also tried other process.StartInfo parameter combinations, but none them can show me the output from node.js, all of them, the command window disappers too quick to see anything clearly.
    Do you think I can use process to run node.js script from CMD?
    I don't know if my environment is different from others or not, I am using Windows 10 Pro (version 21H2), and my current node version is: 19.0.0; I am using X64.
    I wrote all my C# program target .Net 6.0 for x64 CPU.
    Please advise,
    Thanks,

  9. ClearScriptLib commented on Oct 31, 2022

    @ClearScriptLib
    Collaborator

    Hi @zydjohnHotmail,

    I can run this code, however, it seems impossible to see any output from the CCXT node.js script.

    You should be able to capture the output as follows:

    Process p = new();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT_Exchanges\ccxt_all_exchanges.js";
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;
    p.Start();
    var output = p.StandardOutput.ReadToEnd();
    p.WaitForExit();

    Now you can display or process output however you wish.

    Good luck!

  10. zydjohnHotmail commented on Oct 31, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thanks for your code, now, I decied to use the most basic JavaScript, as the following:
    D:\nodejs\CCXT>type hello_world.js
    console.log('Hello World');
    D:\nodejs\CCXT>node hello_world.js
    Hello World

    D:\nodejs\CCXT>
    I think it is basic enough.
    Then I create one Console Project (C#) target either .NET 5 or .NET 6.
    The following is the code:
    using System;
    using System.Diagnostics;

    namespace ConsoleCallCCXT
    {
    public class Program
    {
    static void Main(string[] args)
    {
    Process p = new();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT\hello_world.js.js";
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;
    p.Start();
    var output = p.StandardOutput.ReadToEnd();
    p.WaitForExit();
    Console.Beep();
    }
    }
    }

    When I run this, I can hear beep, but I saw the following error:
    node:internal/modules/cjs/loader:998
    throw err;
    ^

    Error: Cannot find module 'D:\nodejs\CCXT\hello_world.js.js'
    at Module._resolveFilename (node:internal/modules/cjs/loader:995:15)
    at Module._load (node:internal/modules/cjs/loader:841:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:82:12)
    at node:internal/main/run_main_module:23:47 {
    code: 'MODULE_NOT_FOUND',
    requireStack: []
    }

    Node.js v19.0.0

    D:\Helpers\ConsoleCallCCXT\ConsoleCallCCXT\bin\Debug\net6.0\ConsoleCallCCXT.exe (process 13356) exited with code 0.
    To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
    Press any key to close this window . . .
    Please advise on how to fix this?
    It seems to be wired, the most basic JavaScript, why I can't run from console project?

  11. ClearScriptLib commented on Oct 31, 2022

    @ClearScriptLib
    Collaborator

    Hi @zydjohnHotmail,

    Error: Cannot find module 'D:\nodejs\CCXT\hello_world.js.js'

    Your problem might be here:

    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT\hello_world.js.js"; // ← wrong file name?

    Cheers!

  12. zydjohnHotmail commented on Oct 31, 2022

    @zydjohnHotmail
    Author

    Hello:
    Sorry for my typo, I changed the code, now it can run, but I can't see any output "Hello World".
    Any suggestions on this issue?
    Thanks,

  13. ClearScriptLib commented on Oct 31, 2022

    @ClearScriptLib
    Collaborator

    I changed the code, now it can run, but I can't see any output "Hello World".

    The code above captures the Node.js output in the output string variable, but it doesn't display or process it in any way. Try adding a Console.WriteLine(output) or something like that.

  14. zydjohnHotmail commented on Oct 31, 2022

    @zydjohnHotmail
    Author

    Hello:
    Sorry, I don't quite understand how to do this.
    Do you have some code sample, simply shows the "Hello World" in C# console project?
    Thanks,

  15. ClearScriptLib commented on Oct 31, 2022

    @ClearScriptLib
    Collaborator

    Something like this:

    Process p = new();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT\hello_world.js";
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;
    p.Start();
    var output = p.StandardOutput.ReadToEnd();
    p.WaitForExit();
    Console.WriteLine(output); // ← new line here
    Console.Beep();
  16. zydjohnHotmail commented on Oct 31, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thanks for your code, I am now one step further.
    However, this is very specific to console.log output, remember my first CCXT code, use console.log to show all exchanges, it has total 120 items, but console.log shows only the first 100 items.
    Now if I can my C# code to call the first ccxt node script, like this:
    p.StartInfo.Arguments = "/c node D:\nodejs\CCXT_Exchanges\ccxt_all_exchanges.js";
    Then I can get only the first 100 items, is there any way to return all 120 items to C# and show all 120 items in C# project?
    Please advise,
    Thanks,

  17. ClearScriptLib commented on Nov 1, 2022

    @ClearScriptLib
    Collaborator

    Hi @zydjohnHotmail,

    Then I can get only the first 100 items, is there any way to return all 120 items to C# and show all 120 items in C# project?

    The console.log method limits arrays to 100 items, but you can convert your array to a string and log that instead. Try changing your ccxt_all_exchanges.js file so that it looks something like this:

    'use strict';
    const ccxt = require('ccxt');
    console.log(ccxt.version);
    var all_exchanges = ccxt.exchanges;
    console.log(JSON.stringify(all_exchanges, undefined, 4));

    Here's another possibility:

    'use strict';
    const ccxt = require('ccxt');
    const util = require('util')
    console.log(ccxt.version);
    var all_exchanges = ccxt.exchanges;
    console.log(util.inspect(all_exchanges, { maxArrayLength: null }));

    Good luck!

  18. zydjohnHotmail commented on Nov 2, 2022

    @zydjohnHotmail
    Author

    Hello:
    Thanks for your help.
    I am trying now to see if I can use ClearScript, not console to get async function results. The code doesn’t use any personal data, so everyone can call it.
    The following is the Node.js code:
    D:\nodejs\CCXT_Binance>type Binance1PairOrderBook.js
    const ccxt = require('ccxt');
    console.log(ccxt.version);

    if (process.argv.length != 3)
    {
    console.error('Usage: BTC/USDT');
    console.error('Please try again!');
    process.exit(1);
    }
    const [nodejs, script1, pair1] = process.argv;

    let exchange = new ccxt.binance
    ({
    'adjustForTimeDifference': true,
    defaultType: 'spot',
    'verbose': false
    });

    const pair1OrderBook = async (pair1) => {
    try
    {
    await exchange.loadMarkets();
    const orderbook1 = await exchange.fetchOrderBook(pair1);
    if (typeof orderbook1 !== 'undefined')
    {
    const json_orderbook = JSON.stringify(orderbook1);
    console.log(json_orderbook);
    }
    else
    {
    const obj_orderbook0 = ({ 'Symbol': pair1, 'Data': [] });
    const json_orderbook0 = JSON.stringify(obj_orderbook0);
    console.log(json_orderbook0);
    }
    }
    catch (err)
    {
    console.error(err)
    }
    };
    pair1OrderBook(pair1);

    To use this code, call this with one cryptocurrency trading pair, the biggest pair is: BTC/USDT, but the output contains too many rows, so calling it with not very active pairs, like this:
    D:\nodejs\CCXT_Binance>node Binance1PairOrderBook.js FXS/USDT
    2.1.3
    (node:20492) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
    (Use node --trace-warnings ... to show where the warning was created)
    {"symbol":"FXS/USDT","bids":[[6.436,5.5],[6.432,51.4],[6.428,94.5],[6.424,1245.3],[6.421,5],[6.416,75.1],[6.415,277.2],[6.414,642],[6.412,391.8],[6.411,521.1],[6.41,334.8],[6.407,546.8],[6.403,31],[6.402,57.5],[6.4,26],[6.398,4.1],[6.396,11.8],[6.393,2.4],[6.392,3.9],[6.391,750],[6.39,8.2],[6.388,2.4],[6.387,18.2],[6.386,3.2],[6.38,39],[6.377,9.9],[6.371,58],[6.368,5.5],[6.366,1.6],[6.361,4.1],[6.357,68.5],[6.356,3],[6.354,10.9],[6.352,11.3],[6.35,206.8],[6.337,1499.3],[6.336,73.2],[6.333,4.8],[6.328,5.3],[6.327,131],[6.324,4.1],[6.323,11.4],[6.319,8.2],[6.317,2.4],[6.311,7.9],[6.31,2],[6.309,2.4],[6.305,4.6],[6.3,4.7],[6.292,76.7],[6.288,4.1],[6.283,8.2],[6.28,5.3],[6.274,82.4],[6.272,1.6],[6.259,104],[6.252,4.1],[6.25,104.8],[6.248,8.2],[6.246,4.9],[6.245,234.2],[6.244,109.6],[6.243,8.7],[6.242,2.5],[6.241,36],[6.232,5.4],[6.229,112.1],[6.225,259.2],[6.224,10.3],[6.223,221.7],[6.216,4.1],[6.212,8.2],[6.21,2.4],[6.2,24.2],[6.185,5.4],[6.18,4.1],[6.177,8.2],[6.171,4.5],[6.166,4.8],[6.163,12.2],[6.16,19.6],[6.15,8.8],[6.144,4.1],[6.143,2.7],[6.142,8.2],[6.139,5.5],[6.134,4.8],[6.129,740.6],[6.12,1.7],[6.109,4.1],[6.108,6.5],[6.106,8.2],[6.092,5.5],[6.083,4.8],[6.076,3.7],[6.074,4.1],[6.071,8.2],[6.059,9],[6.046,5.5],[6.039,4.1]],"asks":[[6.44,21.3],[6.444,31.6],[6.45,38.4],[6.451,58],[6.452,140.5],[6.453,52.7],[6.457,320.8],[6.461,53.9],[6.464,150],[6.465,12.1],[6.467,315.4],[6.477,3.4],[6.484,4.1],[6.486,18.5],[6.487,5.2],[6.489,48.5],[6.496,8.2],[6.505,500],[6.506,427.4],[6.507,55.9],[6.517,14.4],[6.521,754.1],[6.529,153.8],[6.531,8.2],[6.536,5.2],[6.539,8.8],[6.541,8.4],[6.543,171.2],[6.55,25.5],[6.551,504.6],[6.556,17.5],[6.559,4.1],[6.567,8.2],[6.574,3.7],[6.583,4.8],[6.586,5.1],[6.597,4.1],[6.6,166.6],[6.602,20.4],[6.625,4.3],[6.635,4.1],[6.637,5.1],[6.638,8.2],[6.639,8.3],[6.651,221.3],[6.654,9.3],[6.666,4.8],[6.673,12.3],[6.674,193.1],[6.681,6.1],[6.687,5.1],[6.7,9.3],[6.709,8.2],[6.712,4.1],[6.739,13.2],[6.74,89.5],[6.744,8.2],[6.75,13.2],[6.764,13.1],[6.769,104.7],[6.77,479],[6.773,16.3],[6.779,8.2],[6.784,12],[6.789,4.1],[6.79,5],[6.8,2.2],[6.801,3.1],[6.815,8.2],[6.829,4.1],[6.833,4.8],[6.841,8.1],[6.843,4.9],[6.85,11.5],[6.864,3.1],[6.867,59.9],[6.868,166],[6.869,407.9],[6.875,10.3],[6.886,8.2],[6.895,4.9],[6.907,4.1],[6.911,5.8],[6.912,5.8],[6.916,9.2],[6.921,8.2],[6.943,8.8],[6.944,7.9],[6.948,9],[6.951,10.3],[6.957,8.2],[6.965,22.5],[6.974,32.7],[6.981,473.1],[6.986,3.4],[6.988,4.1],[6.989,3.4],[6.992,8.2],[7,65.2],[7.001,4.8]],"nonce":180573549}

    Or you can call one pair, which exists, but no order book to show, the result like this:
    D:\nodejs\CCXT_Binance>node Binance1PairOrderBook.js ETH/USDC
    2.1.3
    (node:17604) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
    (Use node --trace-warnings ... to show where the warning was created)
    {"symbol":"ETH/USDC","bids":[],"asks":[],"nonce":2090539859}

    Now, I create one WinForms app, and write the following code:
    private async Task Call_CCXT_Get_1Orderbook()
    {
    using V8ScriptEngine engine = new();
    engine.Execute("self = this; setTimeout = () => {}");
    engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableWebLoading;
    engine.Script.done = new ManualResetEventSlim();
    engine.ExecuteDocument(CCXT_JS_Web_Loader_Url);
    engine.Execute(@"
    let exchange = new ccxt.binance
    ({'adjustForTimeDifference': true,
    defaultType: 'spot',
    'verbose': false });
    async function pair1OrderBook(pair1) {
    try
    {
    await exchange.loadMarkets();
    const orderbook1 = await exchange.fetchOrderBook(pair1);
    if (typeof orderbook1 !== 'undefined')
    {
    const json_orderbook = JSON.stringify(orderbook1);
    console.log(json_orderbook);
    }
    else
    {
    const obj_orderbook0 = ({ 'Symbol': pair1, 'Data': [] });
    const json_orderbook0 = JSON.stringify(obj_orderbook0);
    console.log(json_orderbook0);
    }
    }
    catch (err) {
    console.error(err)
    }
    };
    pair1OrderBook(pair1);
    ");
    await engine.Script.pair1OrderBook("BTC/USDT");
    Console.Beep();
    }

    CCXT update very quickly, in the past a few days, it released more than 100 version, so the latest web version is at:
    public const string CCXT_JS_Web_Loader_Url =
    @"https://cdn.jsdelivr.net/npm/ccxt@2.1.3/dist/ccxt.browser.js";

    When I run my code, I got the following error:
    System.Reflection.TargetInvocationException
    HResult=0x80131604
    Message=Exception has been thrown by the target of an invocation.
    Source=System.Private.CoreLib
    StackTrace:
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at System.Delegate.DynamicInvokeImpl(Object[] args)
    at System.Delegate.DynamicInvoke(Object[] args)
    at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
    at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
    --- End of stack trace from previous location ---
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
    at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, WM msg, IntPtr wparam, IntPtr lparam)
    at Interop.User32.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.Interop.Mso.IMsoComponentManager.FPushMessageLoop(UIntPtr dwComponentID, msoloop uReason, Void* pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(msoloop reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(msoloop reason, ApplicationContext context)
    at System.Windows.Forms.Application.Run(Form mainForm)
    at ClearScriptForm.Program.Main() in D:\ArbitBTC\Helpers\ClearScriptForm\ClearScriptForm\Program.cs:line 14

    This exception was originally thrown at this call stack:
    Microsoft.ClearScript.V8.SplitProxy.V8SplitProxyNative.Invoke(System.Func<Microsoft.ClearScript.V8.SplitProxy.IV8SplitProxyNative, T>)
    Microsoft.ClearScript.V8.V8ScriptEngine.ExecuteInternal(Microsoft.ClearScript.UniqueDocumentInfo, string, bool)
    Microsoft.ClearScript.V8.V8ScriptEngine.Execute.AnonymousMethod__0()
    Microsoft.ClearScript.ScriptEngine.ScriptInvokeInternal(System.Func)
    Microsoft.ClearScript.V8.V8ScriptEngine.ScriptInvoke.AnonymousMethod__0()
    Microsoft.ClearScript.V8.SplitProxy.V8SplitProxyManaged.InvokeHostAction(System.IntPtr)

    Inner Exception 1:
    ScriptEngineException: ReferenceError: pair1 is not defined

    Inner Exception 2:
    ScriptEngineException: ReferenceError: pair1 is not defined

    Please advise on how to fix this. I think this way is much better than using CMD console output.
    However, I can’t figure this out.
    Thanks,

  19. ClearScriptLib commented on Nov 3, 2022

    @ClearScriptLib
    Collaborator

    Please advise on how to fix this.

    Here's the last line of your script:

    pair1OrderBook(pair1);

    The script fails at that line because pair1 isn't defined. You've defined a function (pair1OrderBook) that has a parameter named pair1, but there's nothing with that name that's visible at the top level.

    If you remove that line, the script should succeed, and you should be able to call pair1OrderBook from the host, but again, the CCXT code is likely to fail in ClearScript due to the lack of web APIs such as fetch.

  20. locked and limited conversation to collaborators on Nov 3, 2022
  21. converted this issue into a discussion #440 on Nov 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions