git ssb

0+

wanderer🌟 / js-primea-objects



Tree: 94b5daa6362ac3c9f4a4c781894a73ad2c5160c5

Files: 94b5daa6362ac3c9f4a4c781894a73ad2c5160c5 / index.js

5565 bytesRaw
1const crypto = require('crypto')
2const cbor = require('borc')
3const EventEmitter = require('events')
4const Buffer = require('safe-buffer').Buffer
5
6const TAGS = {
7 id: 41,
8 link: 42,
9 func: 43,
10 mod: 44
11}
12
13/**
14 * a cbor decoder for the objects
15 * @type {Object}
16 */
17const decoder = new cbor.Decoder({
18 tags: {
19 [TAGS.id]: val => new ID(val),
20 [TAGS.func]: val => new FunctionRef({
21 identifier: val[0],
22 params: val[1],
23 actorID: val[2],
24 gas: val[3]
25 }),
26 [TAGS.mod]: val => new ModuleRef(...val),
27 [TAGS.link]: val => {
28 return {
29 '/': val
30 }
31 }
32 }
33})
34
35/**
36 * an ID
37 */
38class ID {
39 /*
40 * @param {Buffer} id - the id as an buffer
41 */
42 constructor (id) {
43 this.id = id
44 }
45
46 toString () {
47 return this.id.toString('hex')
48 }
49
50 toJSON () {
51 return `0x${this.toString()}`
52 }
53
54 static fromJSON (arg) {
55 const { fromHex } = require('./utils')
56 return new ID(fromHex(arg))
57 }
58
59 encodeCBOR (gen) {
60 return gen.write(new cbor.Tagged(TAGS.id, this.id))
61 }
62}
63
64/**
65 * A function reference
66 */
67class FunctionRef {
68 /**
69 * @param {Object} opts
70 * @param {*} opts.identifier - the function's identifier
71 * @param {ID} opts.actorID - the id of the actor
72 * @param {Array} opts.params - the params of the function
73 */
74 constructor (opts) {
75 this.identifier = opts.identifier
76 this.actorID = opts.actorID
77 this.params = opts.params
78 this.gas = opts.gas || 0
79 }
80
81 encodeCBOR (gen) {
82 return gen.write(new cbor.Tagged(TAGS.func, [
83 this.identifier,
84 this.params,
85 this.actorID,
86 this.gas
87 ]))
88 }
89
90 toJSON (includeParams = true) {
91 const json = {
92 '@FunctionRef': {
93 actorID: this.actorID.toJSON(),
94 private: this.identifier[0],
95 name: this.identifier[1],
96 gas: this.gas
97 }
98 }
99 if (includeParams) {
100 json['@FunctionRef'].params = this.params
101 }
102 return json
103 }
104
105 static fromJSON (arg) {
106 const data = arg['@FunctionRef']
107 return new FunctionRef({
108 identifier: [data.private, data.name],
109 actorID: ID.fromJSON(data.actorID),
110 params: data.params,
111 gas: data.gas
112 })
113 }
114
115 /**
116 * Creates a copy of the funcRef
117 * @returns {FunctionRef}
118 */
119 copy () {
120 return new FunctionRef({
121 identifier: this.identifier,
122 actorID: this.actorID,
123 params: this.params,
124 gas: this.gas
125 })
126 }
127}
128
129/**
130 * A module reference
131 */
132class ModuleRef {
133 /**
134 * @param {Object} exports - a map of exported function to params for the funcion if any
135 * @param {ID} id - the id of the actor
136 */
137 constructor (exports, id) {
138 this.exports = exports
139 this.id = id
140 }
141
142 /**
143 * return a function refernce given the name of the function
144 * @param {string} name
145 * @returns {FunctionRef}
146 */
147 getFuncRef (name) {
148 const params = this.exports[name]
149
150 return new FunctionRef({
151 identifier: [false, name],
152 params,
153 actorID: this.id
154 })
155 }
156
157 toJSON (includeExports = true) {
158 const json = {
159 '@ModuleRef': {
160 id: this.id.toJSON()
161 }
162 }
163 if (includeExports) {
164 json['@ModuleRef'].exports = this.exports
165 }
166 return json
167 }
168
169 static fromJSON (arg) {
170 const data = arg['@ModuleRef']
171 return new ModuleRef(data.exports, ID.fromJSON(data.id))
172 }
173
174 encodeCBOR (gen) {
175 return gen.write(new cbor.Tagged(TAGS.mod, [this.exports, this.id]))
176 }
177}
178
179/**
180 * This implements Messages for Primea
181 */
182class Message extends EventEmitter {
183 /**
184 * @param {Object} opts
185 * @param {ArrayBuffer} opts.data - the payload of the message
186 * @param {Array<Object>} opts.caps - an array of capabilities to send in the message
187 */
188 constructor (opts) {
189 super()
190 const defaults = this.constructor.defaults
191 this._opts = Object.assign(defaults, opts)
192 Object.keys(this._opts).forEach(key => {
193 Object.defineProperty(this, key, {
194 get: function () {
195 return this._opts[key]
196 },
197 set: function (y) {
198 this._opts[key] = y
199 }
200 })
201 })
202 }
203
204 static get defaults () {
205 return {
206 ticks: 0,
207 funcRef: null,
208 funcArguments: [],
209 funcParameters: [],
210 _fromId: new ID(Buffer.alloc(20)),
211 _fromTicks: 0
212 }
213 }
214}
215
216/**
217 * returns the type that the object is
218 * @param {*} obj
219 * @return {String}
220 */
221function getType (obj) {
222 if (obj) {
223 if (Buffer.isBuffer(obj)) {
224 return 'data'
225 } else if (Array.isArray(obj)) {
226 return 'elem'
227 } else if (obj['/']) {
228 return 'link'
229 } else if (obj.constructor === Message) {
230 return 'message'
231 } else if (obj.constructor === ID) {
232 return 'id'
233 } else if (obj.constructor === FunctionRef) {
234 return 'func'
235 } else if (obj.constructor === ModuleRef) {
236 return 'mod'
237 }
238 }
239 return 'invalid'
240}
241
242/**
243 * returns the ID of an actor
244 * @param {Object} id
245 * @param {Number} id.nonce - the actor's nonce
246 * @param {ID} id.parent - the actor's parent's ID
247 * @return {ID}
248 */
249function generateActorId (id) {
250 const encoded = _encodeActorId(id)
251 const hashed = _hash(encoded)
252 return new ID(hashed)
253}
254
255function _encodeActorId (id) {
256 if (id.parent) {
257 return cbor.encode([id.nonce, id.parent.id])
258 } else {
259 return cbor.encode([id.nonce, null])
260 }
261}
262
263function _hash (buf) {
264 const hash = crypto.createHash('sha256')
265 hash.update(buf)
266 return hash.digest().slice(0, 20)
267}
268
269module.exports = {
270 Message,
271 ID,
272 FunctionRef,
273 ModuleRef,
274 decoder,
275 getType,
276 generateActorId
277}
278

Built with git-ssb-web