Coder Social home page Coder Social logo

nasateam / nasa.js Goto Github PK

View Code? Open in Web Editor NEW
121.0 7.0 8.0 221 KB

星云链 DApp 客户端开发框架,轻量,易用 | Lightweight and friendly util library for DApp development on Nebulas Blockchain.

License: GNU Lesser General Public License v3.0

JavaScript 100.00%
dapp nebulas blockchain

nasa.js's Introduction

Nasa.js

Lightweight and friendly util library for DApp development on Nebulas Blockchain.

星云链 DApp 客户端开发框架,轻量,易用。

使用说明

安装

  • 可以使用 npm 安装:

     $ npm install nasa.js
  • 也可以在页面中直接加载 CDN 版本:

     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/nasa.min.js"></script>

文档

  • 安装和使用 —— 如何把 Nasa.js 整合到自己的作品中
  • API 文档 —— 详尽的 API 使用说明
  • 功能演示 —— 无需安装,在线体验 Nasa.js 的各项功能

价值是什么?

星云官方 JS SDK(neb.js 和 nebPay)功能完备,我为什么还要使用 Nasa.js?

  • 平衡:Nasa.js 追求 “体积” 与 “功能” 之间的最佳平衡——用小巧的体积覆盖 90% 的 DApp 功能需求,满足你对网页性能的极致追求。

  • 友好:专为 Web 前端工程师设计,把常见场景封装为高层 API,符合你的直觉和开发习惯。

功 能 neb.js
完整版
neb.js
基础版
nebPay Nasa.js
完整对接星云 HTTP 接口
部署合约
向指定地址转账 [1] [1] [2]
调用合约(写入数据) [1] [1]
调用合约(查询数据)
查询交易结果(通过 txHash)
查询交易结果(通过交易流水号)
手机页面唤起手机钱包 [4]
手机钱包扫码交易 [2]
获取当前用户钱包地址 [5]
管理合约地址与当前环境
分析当前浏览器环境
常用工具方法 [6]
文件体积 [9] 155 KiB 9.7 KiB 21 KiB < 30 KiB
  • [1] 此功能通过唤起 “星云钱包 Chrome 扩展” 或 “星云手机钱包 App” 来实现。
  • [2] Nasa.js 暂未直接实现此功能。但由于 Nasa.js 打包了完整的 nebPay,开发者目前需要直接使用 nebPay 来实现此功能。
  • [4] 在手机浏览器(iOS Safari 或 Android Chrome 等)中调用 “星云手机钱包 App” 完成交易。
  • [5] 此功能依赖 “星云钱包 Chrome 扩展” 实现。
  • [6] 包括合约管理、判断地址/TxHash/交易流水号是否合法等工具方法。
  • [9] 包含所有外部依赖的 dist 文件在 min + Gzip 之后的体积。

谁在用?


星云水浒

🏆 星云激励计划周亚军

星云链定时器

🌟 星云激励计划优秀奖

星云 Wiki

🌟 星云激励计划优秀奖

Nasa.js Demo

💡 星云激励计划新应用奖

表白墙斯密达

💡 星云激励计划新应用奖

我是预言帝

💡 星云激励计划新应用奖

常见问题

Nasa.js 到底是 “library” 还是 “框架”?

Nasa.js 提供了丰富的 API,你可以把它当作库来用,只在你需要的时候调用某几个 API。你也可以让它帮你管理合约地址和当前环境,此时 Nasa.js 将为你提供更多便利,就像一个框架那样。

未来,Nasa.js 将为常见开发场景提供更完整的解决方案,成为一个更加称职的开发框架。

Nasa.js 可以独立使用吗?需要同时加载其它依赖吗?

Nasa.js 的 dist 文件已经把所有外部依赖都打包进来了,因此可以独立使用。

我的 DApp 已经加载了 neb.js 和 nebPay 了,可以同时使用 Nasa.js 吗?

在同一页面中同时加载这三者,并不会发生冲突,但这样对网页性能并没有好处。优化建议如下:

  • 如果你的 DApp 加载 neb.js 只是为了向合约查询数据,则建议把相关代码迁移到 Nasa.js。这样你的 DApp 就不需要加载 neb.js 了。

  • 由于 Nasa.js 本身已经打包了 nebPay 的源码,因此你不需要重复加载 nebPay。使用 Nasa.nebPay 即可以取代你代码中的 nebPay 实例,详情参见 此文档

我需要的某个功能 Nasa.js 还不支持,怎么办?

来给 Nasa.js 提 issue 吧!


参与开发

社区

微信群

有任何关于 Nasa.js 的疑问,欢迎加群讨论!请加群主微信号 130-5994-1270,群主会拉你入群。

活动

贡献者  

姓名 贡献 [*] 备注
@cssmagic 💻 🚇 ⚠️ 📖 ✅ ... 创始人
@newraina 💻 🚇 👀 🤔 开发团队成员
@salmonx(风) 🐛
@smallke(夏日小可) 🐛
希望之石 🤔
@Heasn 🤔
bokehlicia 🎨 Logo 图片作者

[*] These legends follow the emoji-key of "all-contributors" specification. Contributions of any kind are welcome!


Thanks

Nasa.js is based on these open source projects:

Nasa.js team is using JetBrains IDE (WebStorm) with Open Source License:

  • WebStorm Logo

License

LGPL-3.0

nasa.js's People

Contributors

cssmagic avatar newraina avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nasa.js's Issues

localStorage 字段说明

  • ext_installed_ever —— 装过钱包扩展,这样 ready() 会多等一等
  • last_used_addr —— 用户上次用过的钱包地址

记录一下钱包扩展近期的更新

chrome-extension://gehjkhmhclgnkkhpfamakecfgakkfkco/html/welcome.html

Release Notes of NasExtWallet

0.1.4

Add feedback message for posting serialNumber to server. If serialNumber is failed to be posted to server, you should not use queryPayInfo(serialNumber) to query transaction results, please use neb.api.getTransactionReceipt instead.

After a transaction is send, there should be an feedback that if the serialNumber is posted to server successfully. Hence an attribute serialNumber_status is added to the return value for listener(serialNumber, result). the result is:

{
    "txhash": "ae41d5459fc8db5ffaee5416585e0874d2324d258258b8c59cda789a04934e1a",
    "contract_address": "",
    "error": "{\"timestamp\":1531231627789,\"status\":400,\"error\":\"Bad Request\",\"exception\":\"org.springframework.web.bind.MissingServletRequestParameterException\",\"message\":\"Required String parameter 'payId' is not present\",\"path\":\"/api/pay\"}"
}

If the error is not empty, it means that the serialNumber is not posted to the server, then you should not use nebpay.queryPayInfo.

0.1.3

Update get account address api: NasExtWallet.getUserAddress. Now you can easily get the user address.

    var userAddress;
    NasExtWallet.getUserAddress(function(addr){
        userAddress = addr;
        console.log("user address is : " + addr)
    })

Notice: How to debug with local html file

Please note that chrome extension installed from Google Web Store cannot interact with local page files by default.

If you need to test your local page files with this extension, please check the options "Allow access to file URLs" at extension setting, just copy this link to chrome address bar: chrome://extensions/?id=gehjkhmhclgnkkhpfamakecfgakkfkco

[公告] 💰 有奖征集 bug:最高奖 5 NAS

Nasa.js 是星云链第一款 DApp 客户端开发框架,轻量,易用。

活动规则

  • 在 Nasa.js 的演示页面测试各个 API:

    • 发现一个未知 bug 奖 0.5 NAS(如果是 VIP 则奖 1 NAS);
    • 发现一个未知的高危 bug 奖 2 NAS(如果是 VIP 则奖 5 NAS)。
  • 请在本 repo 提 issue,并描述详细的浏览器环境和重现步骤。无法重现的 issue 无效;与已有 issue 重复无效。

  • 活动截止到 2018-07-06 晚;本活动的最终解释权属于 Nasa.js 团队。

相关链接

新需求:发起交易时指定 gas

记录群友讨论:

Orange

要能够直接设定gas就更好

希望之石
直接设定 GAS 得插件钱包支持

CSS魔法
@ Orange “直接设定 Gas” 这事儿,我再研究研究。

Orange
好的,看看是不是插件没开放接口还是怎么的

深水可乐(自建星云节点)
头号玩家的gas limit确实是设高些才能用来着

nl.lamp.games 星云大竞猜
设置gas要用neb.js nebPay.js里的方法没法设置gas

nl.lamp.games 星云大竞猜
目测需要把两部分代码合并一下

nl.lamp.games 星云大竞猜
neb.js 里的call 和 nebPay.js

API 文档 (v0.1.x)


⚠️ 本文档适用于 Nasa.js v0.1.x,可能已过时。


概述

总体设计

  • 纯静态的 API 设计风格。除了极度常用的几个核心 API 以外,常规 API 都采用 Nasa.module.method() 这样的命名方式。

  • All-in-One 的打包方式。把所有外部依赖打包到在一起,对外暴露一个全局变量 Nasa

文档约定

  • 如果某个 API 未描述 “返回值”,则表示它没有返回值;如果未描述 “参数”,则表示不需要参数。

  • 在某个 API(比如 Nasa.module.method())的描述中,当提及自身时,可能会省略其命名空间,只写成 .method()

  • .foo(bar = 1) 表示 foo 方法的参数 bar 有默认值 1,因此可省略。

依赖库  

所有外部依赖都会被打包进 Nasa.js 的 dist 文件中,你可以通过以下属性引用它们。

Nasa.nebPay

nebPay 的 API 命名空间。无需实例化,直接使用即可:

Nasa.nebPay.pay(to, value, options)

⚠️ Nasa.js v0.1.x 内置的 nebPay 版本为 v0.1.0。

Nasa.BigNumber

BigNumber 构造函数。

// create an instance of a BigNumber object
const value = Nasa.BigNumber(123.4567)

// config BigNumber
Nasa.BigNumber.config({ ROUNDING_MODE: 0 })

⚠️ Nasa.js 内置的 BigNumber 实际上是内置的 nebPay 所包含的 BigNumber。

常量  

当你需要输出或匹配一些固定值时,不如直接引用 Nasa.js 帮你定义好的常量,以免拼写错误。

版本信息

  • Nasa.VERSION -- 当前页面加载的 Nasa.js 的版本号,比如 '0.1.4'

⚠️ Nasa.js 从 v0.1.4 开始提供此属性。

错误信息

  • Nasa.error.NETWORK_ERROR -- 网络错误
  • Nasa.error.SERVER_ERROR -- 服务器错误
  • …… -- 更多错误信息详见各 API 的描述

环境名  

  • Nasa.env.MAIN -- 'mainnet'
  • Nasa.env.TEST -- 'testnet'
  • Nasa.env.LOCAL -- 'local'
  • Nasa.env.MAINNET -- Nasa.env.MAIN 的别名
  • Nasa.env.TESTNET -- Nasa.env.TEST 的别名

核心 API  

Nasa.call(contract, fnName, args = [], options = {})  

调用合约方法,并向链写入数据,因此需要以交易的方式实现(一般称作 “写入型调用” 或 “交易型调用”)。

参数

  • contract -- 字符串。合约地址。如果你用 Nasa.contract.set() API 配置了合约,则这里也可以传入合约名;如果你配置了默认合约,且此参数为空值或假值时,将取默认合约。
  • fnName -- 字符串。合约方法名。
  • args -- 数组。传给合约方法的参数。不需要转换成 JSON。示例如下:
    • 不传参数 -- []
    • 传一个参数 1 -- [1]
    • 传多个参数 1, 2, 3 -- [1, 2, 3]
  • options -- 对象。附加选项。可选的 key 如下:
    • value -- 字符串。调用合约同时转账的数额(单位 NAS)。

返回值

Promise。处理结果如下:

  • Fulfilled:字符串。交易流水号,可通过 Nasa.checkTx() 查询交易状态和调用结果。

  • Rejected:

    错误原因 错误消息
    传入的参数无效 Nasa.error.INVALID_ARG
    用户取消交易 Nasa.error.TX_REJECTED_BY_USER
    服务器不稳定 Nasa.error.SERVER_ERROR
    钱包扩展没有导入钱包 Nasa.error.EXTENSION_NO_WALLET

Nasa.query(contract, fnName, args = [])

向合约查询数据,不需要向链写入数据,因此不需要发起交易(一般称作 “读取型调用” 或 “查询型调用”)。

参数

(同 Nasa.call() 的参数,但没有 options 参数。)

返回值

Promise。处理结果如下:

  • Fulfilled:合约调用结果。已帮你把 JSON 解析好了。

  • Rejected:

    错误原因 错误消息
    传入的参数无效 Nasa.error.INVALID_ARG
    得到的响应无效 Nasa.error.INVALID_RESPONSE
    网络错误 Nasa.error.NETWORK_ERROR
    JSON 解析错误 Nasa.error.INVALID_JSON
    合约调用错误 错误信息 [*]

    [*] 可能有以下情况:

    • 'contract check failed' -- 合约不存在
    • 'insufficient balance' -- 用户钱包无余额
    • 'Call: TypeError: ...' -- 合约函数运行时错误

Nasa.checkTx(payId)  

查询交易结果。

大家都知道交易完成需要等待矿工打包,不是一次查询就可以得到交易结果。此 API 会自动轮询,直到拿到交易结果(或多次轮询后超时失败)。

参数

  • payId -- 字符串。交易流水号(亦称 “交易序列号” 或 “serial number”)。

⚠️ 注意:目前只支持查询 payId,不支持查询 txHash。

返回值

Promise。处理结果如下:

  • Fulfilled:对象。交易详细信息,基本格式如下:

     {
     	"data": "...base64...",  // 就是 {Function, Args} 的 JSON 的 base64
     	"contract_address": "",
     	"type": "call",  // or "binary"
     	"nonce": 7,
     	"gas_price": "1000000",
     	"gas_limit": "200000",
     	"gas_used": "23702",
     	"chainId": 1001,
     	"from": "...user...addr...",
     	"to": "...contract...addr...",
     	"value": "0",
     	"hash": "...tx...hash...",
     	"status": 1,	// 0-失败 1-成功 2-待定
     	"timestamp": 1527525664,
     	"execute_result": "{}",	// 合约执行的返回值,JSON 格式。
     	"execute_error": "",
     	"result": {}  // 👉 合约执行的返回值,已帮你把 JSON 解析好了。
     }
  • Rejected:

    错误原因 错误消息
    传入的参数无效 Nasa.error.INVALID_ARG
    交易错误(合约调用错误) Nasa.error.CALL_FAILED
    交易错误(转账错误) Nasa.error.TX_FAILED
    交易状态未知 Nasa.error.TX_STATUS_UNKNOWN
    查询超时(一分钟内都没有得到交易结果) Nasa.error.REQUEST_TIMEOUT
    网络错误 Nasa.error.NETWORK_ERROR

Nasa.pay(addr, value = '0')

⚠️ 计划中,暂未实现!

向指定用户转账。

参数

  • addr -- 字符串。接收方的钱包地址。
  • value -- 字符串。转账数额(单位 NAS)。

返回值

(同 Nasa.call() 的返回值)

合约  

你的 DApp 可能会用到多个环境下的多个合约,因此建议你使用 Nasa.js 来帮助你管理合约地址。

Nasa.contract.set(config)  

配置 DApp 所需要的合约地址,便于管理和使用。你需要为每个合约起个名字——如果你有起名困难症,也可以使用 'contract1' 这样的名字,只要你记得谁是谁就行。

可配置多个合约。建议至少要有一个默认合约(名为 'default')——这样其它 API 就可以自动找到这个默认合约了,无需你手动指定。

参数

  • config -- 对象。具体格式见示例。

示例

假设你在写一个博客应用,需要用到三个合约(分别用于实现主逻辑、处理文章、处理评论),同时每个合约拥有三个版本(本地环境、测试网、主网),则可以像这样把它们管理起来:

Nasa.contract.set({
	default: {
		local:   '...contract...addr...',
		testnet: '...contract...addr...',
		mainnet: '...contract...addr...',
	},
	contract_article: {
		/* ... */
	},
	contract_comment: {
		/* ... */
	}
})

注意事项

  • 不合法的环境名和合约地址会被丢弃。

Nasa.contract.get(contractName = 'default')  

获取指定名称的合约的地址。

参数

  • contractName -- 字符串。合约名称。如果此参数为空值或假值,则取 'default'

返回值

字符串。合约地址。此 API 会自动匹配 “当前环境”——即你通过 Nasa.env.set() API 指定的环境。

如果该合约未定义当前环境下的地址,则返回空字符串。

环境配置

Nasa.env.set(envName)  

设置当前环境。

如果不指定通过此 API 指定当前环境,则默认运行于主网环境。

参数

Nasa.env.get()  

获取当前环境。

其它 API 会用到此 API,比如 Nasa.contract.get()

用户

Nasa.user.getAddr()  

获取当前用户的钱包地址。此功能依赖 “星云钱包 Chrome 扩展” 来实现,因此只在 PC 端有效;如果扩展移除了相关接口,则此 API 也将失效。

返回值

Promise。处理结果如下:

  • Fulfilled:字符串。用户地址。

  • Rejected:

    错误原因 错误消息
    当前浏览器不是桌面版 Chrome Nasa.error.EXTENSION_NOT_INSTALLED
    当前浏览器没有安装 “星云钱包 Chrome 扩展” Nasa.error.EXTENSION_NOT_INSTALLED
    “星云钱包 Chrome 扩展” 没有导入钱包 Nasa.error.EXTENSION_TIMEOUT
    “星云钱包 Chrome 扩展” 不再支持此功能 Nasa.error.EXTENSION_TIMEOUT

Nasa.user.getAvatar(addr)

⚠️ 计划中,暂未实现!

获取指定用户的头像。头像生成算法与 “星云钱包 Chrome 扩展” 一致。

参数

  • addr -- 字符串。钱包地址。

返回值

  • 字符串。采用 Base64 编码的图片数据,并已加 data: 协议前缀。可以直接填充到 <img> 元素的 src 属性,也可以赋值给元素的 .style.backgroundImage 属性。

浏览器环境

Nasa.ua.isSupported()

返回值

布尔值。当前浏览器是否可以正常运行 Nasa.js。基于特性检测来判断。

注:目前 Ajax 由 Fetch() API 实现,可能不支持部分老浏览器。在后续的版本中,可能会把 Ajax 的实现换成 XHR,以提升兼容性。

Nasa.ua.isMobileDevice()

返回值

布尔值。当前浏览器是否运行于移动设备。基于 User Agent 字符串来判断。

所有 Android 和 iOS 设备(包括 iPad)都会被视为移动设备。

Nasa.ua.isDesktopDevice()

返回值

布尔值。当前浏览器是否运行于桌面设备。基于 User Agent 字符串来判断。

非移动设备,即被视为桌面设备。

Nasa.ua.isDesktopChrome()

返回值

布尔值。当前浏览器是否是桌面版 Chrome。基于 User Agent 字符串来判断。

Nasa.ua.isWeChat()

返回值

布尔值。当前浏览器是否是微信。基于 User Agent 字符串来判断。

Nasa.ua.isWalletExtensionInstalled()

返回值

布尔值。判断 “星云钱包 Chrome 扩展” 是否已安装。

注:此功能依赖扩展向页面中注入的脚本来判断,而由于扩展注入脚本需要一点点时间,因此,在页面最顶部运行此 API 不一定会得到正确的结果。

Nasa.ua.isWalletMobileAppInstalled([status])

⚠️ 计划中,暂未实现!

运行在手机浏览器中的页面实际上无从判断 “星云手机钱包 App” 是否已安装,因此,作为开发者,只能向用户询问是否已安装,记住用户的回答,然后走向不同的分支流程。

这个 API 帮助开发者记住用户的回答,有 getter 与 setter 两种模式。

  • Setter: .isWalletMobileAppInstalled(status)

    保存用户的回答。

    参数status -- 布尔值。用户是否声称自己已安装 “星云手机钱包 App”。

  • Getter: .isWalletMobileAppInstalled()

    获取已保存的回答。

    返回值

    • true -- 之前保存过的用户的回答:已安装
    • false -- 之前保存过的用户的回答:未安装
    • undefined -- 之前没有保存过用户的回答

注:此 API 通过本地存储作为持久化存储。

工具方法

Nasa.util.isValidAddr(str)

判断是否是合法的地址(钱包地址或合约地址)。

参数

  • str -- 字符串。待检测的地址。

返回值

布尔值。是否合法。

Nasa.util.isValidTxHash(str)

判断是否是合法的 TxHash(交易哈希)。

参数

  • str -- 字符串。待检测的 TxHash。

返回值

布尔值。是否合法。

Nasa.util.isValidPayId(str)

判断是否是合法的交易流水号。

参数

  • str -- 字符串。待检测的交易流水号。

返回值

布尔值。是否合法。


安装和使用

安装和使用

基本操作

  1. 通过 npm 安装:

    npm install nasa.js
  2. 在页面中引用 dist 文件(最终发行的打包文件):

    <script src='./node_modules/nasa.js/dist/nasa.js'></script>
    <script>
    // use `Nasa` as a global variant
    alert(Nasa.ua.isSupported())
    </script>

补充说明

  • Nasa.js 一旦加载,就会对外暴露一个全局变量 Nasa。直接使用挂载在它身上的各个 API 即可。

  • Nasa.js 的源码采用 ES6 模块管理,采用 ES6+ 语法。但并不建议以模块的方式引用其源码,因为 dist 文件包含了所有外部依赖,直接使用源码意味着需要操心外部依赖。建议使用者直接使用 dist 文件,并以全局变更的方式使用它。

  • Nasa.js 目前并没有提供任何符合 CommonJS 模块规范的版本,因此不支持以 require('nasa.js') 的方式来引用,不支持 Browserify 打包。

常见问题

如何把 Nasa.js 与其它脚本文件合并到一起?

方法一:可以使用简单的文件拼接方式,把 dist 文件与其它脚本文件合并。

方法二:如果你使用的打包工具支持 ES6 模块规范,可以把 dist 文件当作一个模块来引用,并打包到自己的 bundle 中。具体代码是这样的:

import 'nasa.js/dist/nasa.js'
	
// use `Nasa` as a global variant
alert(Nasa.ua.isSupported())

v0.2.x 内测 API


⚠️ 以下 API 是实验性功能,仅供内测。在未来的测试版中,其行为很可能有变化;甚至可能在正式版中取消。


自定义星云 HTTP API Endpoint

新增了 Nasa.config() API,可在不同环境下指定对应的 endpoint。

Nasa.config({
    [Nasa.env.LOCAL]: {
        endpoint: 'https://local.foo.bar/',
    },
    [Nasa.env.TEST]: {
        endpoint: 'https://testnet.foo.bar/',
    },
    [Nasa.env.MAIN]: {
        endpoint: 'https://mainnet.foo.bar/',
    },
})

在使用 .query() 时指定 from 地址

这个 API 增加了第四个参数 options,可使用 options.from 指定发出地址。

Nasa.query(contract, fnName, args, {
    from: 'n1bCep7RbeCWQk9EQo48V3TuXEdZLCS7eTn',
})
    .then((data) => {
        // ...
    })

API 文档

概述  

总体设计  

  • 纯静态的 API 设计风格。除了极度常用的几个核心 API 以外,常规 API 都采用 Nasa.module.method() 这样的命名方式。

  • All-in-One 的打包方式。把所有外部依赖打包到在一起,对外暴露一个全局变量 Nasa

文档约定  

  • 如果某个 API 未描述 “返回值”,则表示它没有返回值;如果未描述 “参数”,则表示不需要参数。

  • 在某个 API(比如 Nasa.module.method())的描述中,当提及自身时,可能会省略其命名空间,只写成 .method()

  • .foo(bar = 1) 表示 foo 方法的参数 bar 有默认值 1,因此可省略。

依赖库  

所有外部依赖都会被打包进 Nasa.js 的 dist 文件中,你可以通过以下属性引用它们。

Nasa.nebPay  

nebPay 的 API 命名空间。无需实例化,直接使用即可:

Nasa.nebPay.pay(to, value, options)

⚠️ Nasa.js v0.2.x 内置的 nebPay 版本为 v0.2.x。

Nasa.BigNumber  

BigNumber 构造函数。

// create an instance of a BigNumber object
const value = Nasa.BigNumber(123.4567)

// config BigNumber
Nasa.BigNumber.config({ ROUNDING_MODE: 0 })

⚠️ Nasa.js 内置的 BigNumber 实际上是内置的 nebPay 所包含的 BigNumber。

常量  

当你需要输出或匹配一些固定值时,不如直接引用 Nasa.js 帮你定义好的常量,以免拼写错误。

版本信息  

  • Nasa.VERSION —— 当前页面加载的 Nasa.js 的版本号,比如 '0.1.4'

错误信息  

  • Nasa.error.NETWORK_ERROR —— 网络错误
  • Nasa.error.SERVER_ERROR —— 服务器错误
  • ... —— 更多错误信息详见各 API 的描述

环境名  

  • Nasa.env.MAIN —— 'mainnet'
  • Nasa.env.TEST —— 'testnet'
  • Nasa.env.LOCAL —— 'local'
  • Nasa.env.MAINNET —— Nasa.env.MAIN 的别名
  • Nasa.env.TESTNET —— Nasa.env.TEST 的别名

核心 API  

Nasa.query(contract, fnName, args = [])  

向合约查询数据,不需要向链写入数据,因此不需要发起交易(一般称作 “读取型调用” 或 “查询型调用”)。

⚠️ 注意:如果使用此 API 去调用那些有写数据逻辑的合约方法,并不会实际执行写操作,只是会得到模拟执行的结果,因此此操作也被称作 “simulate call”。

参数

  • contract —— 字符串。合约地址。如果你用 Nasa.contract.set() API 配置了合约,则这里也可以传入合约名;如果你配置了默认合约,且此参数为空值或假值时,将取默认合约。
  • fnName —— 字符串。合约方法名。
  • args —— 数组。传给合约方法的参数。不需要转换成 JSON。示例如下:
    • 不传参数 —— []
    • 传一个参数 1 —— [1]
    • 传多个参数 1, 2, 3 —— [1, 2, 3]

返回值

Promise。处理结果如下:

  • Fulfilled:合约调用结果。格式如下:

     // 正常调用
     {
     	execResult: {},  // 注❶
     	estimateGas: "20490",
     }

    注❶:合约调用返回值。会自动进行 JSON 反序列化,不需你自己解析;如果 JSON 解析失败,则返回原字符串。

     // 调用过程中抛错
     {
     	execError: 'my error msg',  // 注❷
     	estimateGas: "20335",
     }

    注❷:合约调用过程中抛出的错误消息。可能是合约在运行时产生的异常,也可能是合约代码主动抛出的自定义错误。

  • Rejected:

    错误原因 错误消息
    合约地址无效 Nasa.error.INVALID_CONTRACT_ADDR
    传给此 API 的参数无效 Nasa.error.INVALID_ARG
    传给服务器的参数无效 Nasa.error.INVALID_REQUEST
    合约无效(未部署) Nasa.error.INVALID_CONTRACT
    服务器过载(或网络错误) Nasa.error.SERVER_ERROR

Nasa.call(contract, fnName, args = [], options = {})  

调用合约方法,并向链写入数据,因此需要以交易的方式实现(一般称作 “写入型调用” 或 “交易型调用”)。

参数

  • contract ——(同 Nasa.query() 的同名参数)
  • fnName ——(同 Nasa.query() 的同名参数)
  • args ——(同 Nasa.query() 的同名参数)
  • options —— 对象。附加选项。可选的 key 如下:
    • value —— 字符串。默认值为 '0' 。调用合约同时转账的数额(单位 NAS)。

返回值

Promise。处理结果如下:

  • Fulfilled:交易的标识信息。格式如下:

     {
     	payId: '...pay...id...',    // 注❶
     	txHash: '...tx...hash...',  // 注❷
     }
    • 注❶:交易流水号,可通过 Nasa.getTxResult() 查询交易状态和调用结果。
    • 注❷:交易哈希,交易在链上的真正标识。⚠️ 注意:
      • 仅在 Chrome 钱包扩展环境下,才有此字段。
      • 请留意 txHash 的拼写。
  • Rejected:

    错误原因 错误消息
    传给此 API 的参数无效 Nasa.error.INVALID_ARG
    用户取消交易 Nasa.error.TX_REJECTED_BY_USER
    服务器不稳定 Nasa.error.SERVER_ERROR
    钱包扩展没有导入钱包 Nasa.error.EXTENSION_NO_WALLET
    钱包扩展发送流水号失败 Nasa.error.PAY_ID_REG_FAILED

Nasa.getTxResult(payId)  

⚠️ 此 API 原名为 Nasa.checkTx()。原名仍然可用,但会在 v0.3.0 时删除。

查询交易结果。

大家都知道交易完成需要等待矿工打包,不是一次查询就可以得到交易结果。此 API 会自动轮询,直到拿到交易结果(或多次轮询后超时失败)。

参数

  • payId —— 字符串。交易流水号(亦称 “交易序列号” 或 “serial number”)。

⚠️ 注意:暂时只支持查询 payId,不支持查询 txHash。

返回值

Promise。处理结果如下:

  • Fulfilled:对象。交易详细信息,基本格式如下:

     {
     	"type": "call",  // or "binary"
     	"nonce": 7,
     	"gasPrice": "1000000",
     	"gasLimit": "200000",
     	"gasUsed": "23702",
     	"chainId": 1001,
     	"from": "...user...addr...",
     	"to": "...contract...addr...",
     	"value": "0",
     	"hash": "...tx...hash...",
     	"status": 1,	// 0-失败 1-成功 2-待定
     	"timestamp": 1527525664,
     	"execResult": {},  // 注❶
     	"execError": {},   // 注❷
     }

    ⚠️ 注意:上述数据格式与星云官方 RPC 接口的返回值不完全一致。

  • Rejected:

    错误原因 错误消息
    传入的参数无效 Nasa.error.INVALID_ARG
    交易状态未知 Nasa.error.TX_STATUS_UNKNOWN
    交易查询超时(一分钟内没有得到交易结果,或交易状态仍为未完成) Nasa.error.TX_TIMEOUT

Nasa.pay(addr, value = '0', options = {})  

⚠️ 计划中,暂未实现!

向指定用户转账。

参数

  • addr —— 字符串。接收方的钱包地址。
  • value —— 字符串。转账数额(单位 NAS)。

返回值

(同 Nasa.call() 的返回值)

Nasa.ready(fn)  

有某些情况下,当我们在页面中判断钱包扩展是否已安装(或试图通过钱包扩展获取信息)时,可能会得到错误的结果——明明装了钱包扩展,但判断为未装。这是因为钱包扩展向页面中注入脚本是需要一点时间的,而在此之前,页面无法判断钱包扩展是否已安装(或与之通信)。

为此,Nasa.js 提供了 .ready() 方法,它的功能和用法类似于 jQuery 的 $(document).ready() 方法。我们把应用的初始化函数传给它就可以了,它会机智地选择在合适的时机执行,避免出现 “明明装了钱包扩展但判断为未装” 的尴尬。

这个方法可以被多次调用,你可以每次传递不同的函数给它,这些函数会依次执行。

参数

  • fn —— 函数。应用的初始化函数。需要注意的是,此函数总是会被异步调用。

示例

Nasa.ready(() => {
	// 这里是安全的执行时机,以下代码可以得到正确的结果
	if (!Nasa.ua.isWalletExtensionInstalled()) {
		alert('请先安装星云钱包 Chrome 扩展!')
	} else {
		Nasa.user.getAddr().then((addr) => {
			alert('您的钱包地址是:\n' + addr)
		})
	}
})
Nasa.ready(() => {
	// 还可以在这里执行另一段初始化逻辑...
})

合约  

你的 DApp 可能会用到多个环境下的多个合约,因此建议你使用 Nasa.js 来帮助你管理合约地址。

Nasa.contract.set(config)  

配置 DApp 所需要的合约地址,便于管理和使用。你需要为每个合约起个名字——如果你有起名困难症,也可以使用 'contract1' 这样的名字,只要你记得谁是谁就行。

可配置多个合约。建议至少要有一个默认合约(名为 'default')——这样其它 API 就可以自动找到这个默认合约了,无需你手动指定。

参数

  • config —— 对象。具体格式见示例。

示例

假设你在写一个博客应用,需要用到三个合约(分别用于实现主逻辑、处理文章、处理评论),同时每个合约拥有三个版本(本地环境、测试网、主网),则可以像这样把它们管理起来:

Nasa.contract.set({
	default: {
		local:   '...contract...addr...',
		testnet: '...contract...addr...',
		mainnet: '...contract...addr...',
	},
	contract_article: {
		/* ... */
	},
	contract_comment: {
		/* ... */
	}
})

注意事项

  • 不合法的环境名和合约地址会被丢弃。

Nasa.contract.get(contractName = 'default')  

获取指定名称的合约的地址。

参数

  • contractName —— 字符串。合约名称。如果此参数为空值或假值,则取 'default'

返回值

字符串。合约地址。此 API 会自动匹配 “当前环境”——即你通过 Nasa.env.set() API 指定的环境。

如果该合约未定义当前环境下的地址,则返回空字符串。

环境配置  

Nasa.env.set(envName)  

设置当前环境。

如果不指定通过此 API 指定当前环境,则默认运行于主网环境。

参数

Nasa.env.get()  

获取当前环境。

其它 API 会用到此 API,比如 Nasa.contract.get()

用户  

Nasa.user.getAddr()  

获取当前用户的钱包地址。此功能依赖 “星云钱包 Chrome 扩展”,因此在移动浏览器中不可用。

💡 提示:使用 Nasa.ready(),可确保在钱包扩展准备就绪之后才使用此 API。

返回值

Promise。处理结果如下:

  • Fulfilled:字符串。用户地址。

  • Rejected:

    错误原因 错误消息
    当前浏览器不是桌面版 Chrome Nasa.error.EXTENSION_NOT_INSTALLED
    当前浏览器没有安装 “星云钱包 Chrome 扩展” Nasa.error.EXTENSION_NOT_INSTALLED
    “星云钱包 Chrome 扩展” 没有导入钱包 Nasa.error.EXTENSION_NO_WALLET

Nasa.user.getAvatar(addr)  

⚠️ 计划中,暂未实现!

获取指定用户的头像。头像生成算法与 “星云钱包 Chrome 扩展” 一致。

参数

  • addr —— 字符串。钱包地址。

返回值

  • 字符串。采用 Base64 编码的图片数据,并已加 data: 协议前缀。可以直接填充到 <img> 元素的 src 属性,也可以赋值给元素的 .style.backgroundImage 属性。

浏览器环境  

Nasa.ua.isSupported()  

返回值

布尔值。当前浏览器是否可以正常运行 Nasa.js。基于特性检测来判断。

注:目前 Ajax 由 Fetch() API 实现,可能不支持部分老浏览器。在后续的版本中,可能会把 Ajax 的实现换成 XHR,以提升兼容性。

Nasa.ua.isMobileDevice()  

返回值

布尔值。当前浏览器是否运行于移动设备。基于 User Agent 字符串来判断。

所有 Android 和 iOS 设备(包括 iPad)都会被视为移动设备。

Nasa.ua.isDesktopDevice()  

返回值

布尔值。当前浏览器是否运行于桌面设备。基于 User Agent 字符串来判断。

非移动设备,即被视为桌面设备。

Nasa.ua.isDesktopChrome()  

返回值

布尔值。当前浏览器是否是桌面版 Chrome。基于 User Agent 字符串来判断。

Nasa.ua.isWalletMobileApp()  

返回值

布尔值。当前浏览器是否星云手机钱包。基于 User Agent 字符串来判断。

Nasa.ua.isNasNano()  

Nasa.ua.isWalletMobileApp() 的别名)

Nasa.ua.isWeChat()  

返回值

布尔值。当前浏览器是否是微信。基于 User Agent 字符串来判断。

Nasa.ua.isWalletExtensionInstalled()  

返回值

布尔值。判断 “星云钱包 Chrome 扩展” 是否已安装。

⚠️ 注意:此功能依赖扩展向页面中注入的脚本来判断,而由于扩展注入脚本需要一点点时间,因此,在页面最顶部运行此 API 不一定会得到正确的结果。

💡 提示:使用 Nasa.ready(),可确保在钱包扩展准备就绪之后才使用此 API。

Nasa.ua.isWalletMobileAppInstalled([status])  

⚠️ 计划中,暂未实现!

运行在手机浏览器中的页面实际上无从判断 “星云手机钱包 App” 是否已安装,因此,作为开发者,只能向用户询问是否已安装,记住用户的回答,然后走向不同的分支流程。

这个 API 帮助开发者记住用户的回答,有 getter 与 setter 两种模式。

  • Setter: .isWalletMobileAppInstalled(status)

    保存用户的回答。

    参数status —— 布尔值。用户是否声称自己已安装 “星云手机钱包 App”。

  • Getter: .isWalletMobileAppInstalled()

    获取已保存的回答。

    返回值

    • true —— 之前保存过的用户的回答:已安装
    • false —— 之前保存过的用户的回答:未安装
    • undefined —— 之前没有保存过用户的回答

注:此 API 通过本地存储作为持久化存储。

工具方法  

Nasa.util.isValidAddr(str)  

判断是否是合法的地址(钱包地址或合约地址)。

参数

  • str —— 字符串。待检测的地址。

返回值

布尔值。是否合法。

Nasa.util.isValidTxHash(str)  

判断是否是合法的 TxHash(交易哈希)。

参数

  • str —— 字符串。待检测的 TxHash。

返回值

布尔值。是否合法。

Nasa.util.isValidPayId(str)  

判断是否是合法的交易流水号。

参数

  • str —— 字符串。待检测的交易流水号。

返回值

布尔值。是否合法。


(完)

`Nasa.user.getAddr()` 有 bug,分析发现原来是钱包扩展的 bug

我只是在测试中发现了一个现象,暂时没有深入阅读钱包扩展的源码。

在每个交互周期内(页面 → 钱包扩展 → 页面),NasExtWallet.getUserAddress() 方法只能承载一个回调。也就是说,连续多次调用 NasExtWallet.getUserAddress(callback),最后一次注册的 callback 会覆盖之前的所有 callback。

比如有以下代码:

NasExtWallet.getUserAddress(function () {
	console.log(1)
})
NasExtWallet.getUserAddress(function () {
	console.log(2)
})
NasExtWallet.getUserAddress(function () {
	console.log(3)
})
NasExtWallet.getUserAddress(function () {
	console.log(4)
})

会在控制台得到 4 4 4 4,而不是 1 2 3 4

v0.2.x 开发计划

破坏性变更

  • query()checkTx() 等接口的返回值风格统一(参见 #18

组件交互

  • 内置 nebPay 升级到 v0.2
  • 适配 nebPay v0.2 的新特性
    • 交易相关 API 增加二维码选项('always'/'never'/'auto'
    • 兼容 debug 选项
    • 可自定义 Gas
  • 适配 Chrome 钱包扩展 v0.1.3+ 的新特性
    • 判断是否已安装钱包扩展的新方法(新老方法并存,在 Nasa.js v0.3 中将只保留新方法)
    • 获取用户地址的新方法(新老方法并存,在 Nasa.js v0.3 中将只保留新方法)
    • 考虑交易流水号发送失败之后的逻辑
    • 推动 Chrome 钱包扩展提供获取当前环境的功能

新增功能

  • Nasa.pay()
  • 为业务代码提供初始化方法 Nasa.ready()
  • 全局配置接口 Nasa.config(),可自定义 endpoint
  • 判断当前浏览器是否为手机钱包 Nasa.ua.isWalletMobileApp()
  • 本地存储相关功能
  • 头像

增强

  • .checkTx() 接受 txHash
  • .query() 自定义 from
  • 完整实现 .isValidAddr() API (参见 #7
  • .contract.set(contractName, contractAddr)

代码组织

  • 重新组织命名空间和模块划分(参见 #16

工具

  • 提供 .d.ts

API 版图(草案)


⚠️ 本文档仅列出 API 发展的可能性,并非明确的开发线路图。


  • Nasa.tx.getTxState(txHash)
  • Nasa.tx.getTxResult(payId|txHash) = Nasa.getTxResult() = Nasa.checkTx() ⚠️
  • Nasa.tx.call(...) = Nasa.call()
  • Nasa.tx.pay(...) = Nasa.pay() 🕘
  • Nasa.tx.payToken(...) = Nasa.payToken()
  • Nasa.tx.getLastPayId()
  • Nasa.tx.getLastTxHash()
  • Nasa.addr.TYPE_NORMAL
  • Nasa.addr.TYPE_CONTRACT
  • Nasa.addr.new()
  • Nasa.addr.getState(addr) = Nasa.user.getState()
  • Nasa.storage.get(key)
  • Nasa.storage.set(key, value)
  • Nasa.neb.getDynasty(height)
  • Nasa.neb.getNodeInfo(node)
  • Nasa.neb.getNebState()
  • Nasa.neb.getGasPrice()

  • ⚠️ —— Deprecated
  • 🕘 —— To be done

如何搭建开发环境

准备工作

  1. 获取本项目的最新代码。
  2. 在项目根目录执行 npm install,安装必要的依赖。

Demo 页面

为便于开发,我们为 demo 页面设置了两种模式:“开发模式” 和 “生产模式”。

在这两种模式下,demo 页面加载的资源是不同的(具体行为可参见 demo/index.html 源码)。本文档只关心 “开发模式”。

文件监听与自动刷新

在项目根目录执行 npm run watch,作用如下:

  • 此命令将持续监听源码的变更,并自动重新编译 demo 页面在 “开发模式” 下所需的 JS 和 CSS 文件。

  • 此命令还将启动 BrowserSync,访问 http://localhost:3098/ 即获得自动刷新效果——当 Nasa.js 源码或 demo 页面的相关源码变更时,demo 页面会自动刷新(或自动更新样式)。

Ctrl + C 可中止此服务。


附:端口配置

开发环境默认使用 88883098 这两个端口。如果这两个端口与其它应用冲突,请按以下步骤修改端口:

  1. .env.example 复制一份,命名为 .env

  2. 修改 .env 文件,把两处端口配置改为空闲的其它端口。

  3. 中止并重新执行 npm run watch 命令。

v0.2.x API 行为变更

Nasa.call()

返回值

👉 原:

Promise - Fulfilled:字符串。交易流水号。

改为:

Promise - Fulfilled:对象。交易流水号和 txHash(如果有),结构如下:

{
	payId: '...pay...id...',
	txHash: '...tx...hash...',
}

⚠️ 仅在 Chrome 钱包扩展环境下,才有可能返回 txHash。

请留意 txHash 的拼写。

Nasa.query()

返回值

👉 原:

合约调用时抛错被视为 Promise - Rejected,错误消息就是执行时抛出的错误消息。

改为:

合约调用时抛错将视为 Promise - Fulfilled(因为查询动作本身并没有发生错误,而且顺利拿到了合约调用结果),错误消息会放在 Promise 返回值的一个字段中。

👉 原:

Promise - Fulfilled:就是 JSON 反序列化之后的值。

改为:

Promise - Fulfilled:对象。合约调用返回值(如果有)和合约调用时的错误消息(如果有),结构如下:

// 正常调用
{
	execResult: {},  // 👉 合约调用返回值 JSON 反序列化之后的值
	estimateGas: "20490",
}

// 调用过程中抛错
{
	execError: 'my error msg',  // 👉 合约调用过程中抛出的错误消息
	estimateGas: "20490",
}

Nasa.checkTx()

改名

⚠️ 此 API 改名为 Nasa.getTxResult()

原名仍然可用,但会在 v0.3.0 时删除。

返回值

👉 原:

合约调用时抛错被视为 Promise - Rejected,错误消息为 Nasa.error.CALL_FAILEDNasa.error.TX_FAILED

改为:

合约调用时抛错将视为 Promise - Fulfilled(因为查询动作本身并没有发生错误,而且顺利拿到了交易状态和结果),错误消息会放在交易详细信息中的一个字段中。

👉 原:

Promise - Fulfilled:把 execute_result 反序列化之后的值存放在 result 字段中。

改为:

Promise - Fulfilled:交易详细信息中提供合约调用返回值(如果有)和合约调用时的错误消息(如果有),示意结构如下:

// 正常调用
{
	"...": "...",  // from、to、gas 等基本信息,不赘述
	"execResult": {}, // 👉 "execute_result" 字段 JSON 反序列化之后的值
}

// 调用过程中抛错
{
	"...": "...",  // from、to、gas 等基本信息,不赘述
	"execError": "my error msg"  // 👉 合约调用过程中抛出的错误消息,不含前缀
}

注意,在交易详细信息中:

  • 星云官方 RPC 接口返回的各字段名如果是 “小蛇形拼写”,将一律转换为 “小驼峰拼写”(比如:gas_pricegasPrice)。

  • 不再提供 execute_resultexecute_error 字段,请直接使用 execResultexecError 字段。

👉 原:

Promise - Rejected:其中 “查询超时(一分钟内都没有得到交易结果)” 的错误消息为 Nasa.error.REQUEST_TIMEOUT

改为:

这种情况下的错误消息为 Nasa.error.TX_TIMEOUT


(完)

构建优化:把合并生成 lib.js 的行为移到 gulpfile 中

Laravel-Mix 有个 bug,当 Laravel-Mix 中有 combine 任务时,每次样式变更时,除了重新编译样式,也会触发 combine 任务重新生成 lib.js,这导致 BrowserSync 刷新页面(实际上纯样式变更是不需要刷新页面的)。

Nasa.NebPay对象自带的方法不能调试测试网~

现在碰到一个在 testnet 遇见的 bug :
Nasa.NebPay 的原型中的 pay 和 queryPayInfo 等方法没有测试网的配置选项,在测试的时候不是很方便,希望和官方的文档保持一致.

我现在的解决方法是:
自己定义callback的 url ,区分开是在测试网还是在主网,官方是通过配置 debug 选项来区分的.

let nbp = new Nasa.NebPay();
window.NasaUrl = Nasa.env.get() !== "mainnet" ? "https://pay.nebulas.io/api/pay" : "https://pay.nebulas.io/api/mainnet/pay";
nbp.pay("n1MikYAYZTB9MRaVZy4Bg47RMxABiYLiET7", "0.01", {
  goods: {
    name: "打赏用户",
    desc: "打赏用户0.01NAS"
  },
  callback: NasaUrl
});

Event 事件支持

目前虽然neb.js 提供了订阅事件的接口,但是从官方人员中得知的时候,这个接口并不稳定。
问题详情
官方给的解决方案是自己运行本地节点,这个方案感觉还是有一点繁琐,有没有可能可以提供其他更加方便的解决方案?

如何构建

准备工作

  1. 获取本项目的最新代码。
  2. 在项目根目录执行 npm install,安装必要的依赖。

开发阶段

一次性

在项目根目录执行 npm run dev,将得到 .tmp/nasa-raw.js 文件。

此文件是 Nasa.js 源码的打包结果,不包含 nebPay 等外部依赖;此文件仅用于 demo 页面的开发模式。

实时更新

在项目根目录执行 npm run watch,将得到 .tmp/nasa-raw.js 文件;此外,脚本还会持续监听 Nasa.js 源码的变更,并持续生成 .tmp/nasa-raw.js 文件。

发布

在发版之前,需要在 package.json 文件中更新 version 字段。

在项目根目录执行 npm run dist,将得到以下文件:

  • dist/nasa.js —— 未经过 Uglify 压缩的版本
  • dist/nasa.min.js —— 已压缩版

这些文件是 Nasa.js 的正式打包结果,包含所有依赖。这些文件将被发布到 npm。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.