Exemplo n.º 1
0
class Wallet(BaseModelMixin, TimestampMixin, db.Model):
    __tablename__ = "wallet"
    # id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # is_delete = db.Column(db.Boolean, nullable=False, default=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    zone_id = db.Column(db.Integer,
                        db.ForeignKey('proposal_zone.id'),
                        primary_key=True)  # 对应 proposal zone id
    currency_id = db.Column(db.Integer,
                            db.ForeignKey('currency.id'),
                            primary_key=True)
    address = db.Column(db.String(255), nullable=True)  # wallet address
    # Nonce code for security checks
    nonce = db.Column(db.String(100), nullable=True)

    @staticmethod
    def recover_address(data: str, signature: str) -> str:
        message = encode_defunct(text=data)
        return w3.eth.account.recover_message(message, signature=signature)

    @staticmethod
    def checkNonce(wallet, signature):
        """
        Check the nonce validity
        :param wallet:
        :return: boolean
        """

        if wallet.nonce == None:
            return False

        result = Wallet.recover_address(wallet.nonce, signature)
        print(wallet.nonce, wallet.address, result)
        return result == wallet.address
Exemplo n.º 2
0
class ProposalLog(BaseModelMixin, TimestampMixin, db.Model):
    """
    proposal log
    """

    __tablename__ = 'proposal_log'

    proposal_id = db.Column(db.Integer,
                            db.ForeignKey('proposal.id'),
                            nullable=False)

    event = db.Column(db.Integer)
    from_value = db.Column(db.Text, nullable=True)  # 操作前的值
    to_value = db.Column(db.Text, nullable=True)  # 操作后的值
    op_user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    op_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)

    @property
    def event_key(self):
        return ProposalLogEvent(self.event).name

    @property
    def operator(self):
        return User.query.filter_by(id=self.op_user_id).first()

    @property
    def creator(self):
        return User.query.filter_by(id=self.creator_id).first()
Exemplo n.º 3
0
class UserWallet(TimestampMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    is_delete = db.Column(db.Boolean, nullable=False, default=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    token_zone_id = db.Column(db.Integer,
                              db.ForeignKey('proposal_zone.id'),
                              nullable=False)  # 对应 proposal zone id
    wallet_addr = db.Column(db.String(255), nullable=False)  # wallet address
Exemplo n.º 4
0
class ProposalZone_Currency(BaseModelMixin, TimestampMixin, db.Model):
    """
    Proposal zone - currency relations
    """
    __tablename__ = 'zone_currency'

    zone_id = db.Column(db.Integer,
                        db.ForeignKey('proposal_zone.id'),
                        primary_key=True)
    currency_id = db.Column(db.Integer,
                            db.ForeignKey('currency.id'),
                            primary_key=True)
Exemplo n.º 5
0
class ProposalClaimTeam(BaseModelMixin, TimestampMixin, db.Model):
    __tablename__ = "proposal_claim_team"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    team_id = db.Column(db.Integer, db.ForeignKey(
        'proposal_claim.id'))
    responsibility = db.Column(db.Text)
    # TODO refactor that in flask dto

    def user(self):
        return User.query.filter_by(id=self.user_id)
Exemplo n.º 6
0
class ProposalClaim(BaseModelMixin, TimestampMixin, db.Model):
    __tablename__ = "proposal_claim"

    claim_id = db.Column(db.String(200), nullable=False, default=uuid4)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    proposal_id = db.Column(db.Integer,
                            db.ForeignKey('proposal.id'),
                            primary_key=True)

    # 申领状态
    # 100 申领中
    # 200 申领通过
    # 300 申领不通过
    # 400 撤销申领
    # 500 提交结果中
    # 600 结果通过
    # 700 结果不通过
    status = db.Column(db.Integer,
                       default=ProposalClaimStatus['claiming'].value)

    # 申领理由
    reason = db.Column(db.Text)
    plan = db.Column(db.Text)

    budget_amount = db.Column(db.DECIMAL, nullable=True)
    budget_currency_id = db.Column(db.Integer,
                                   db.ForeignKey('currency.id'),
                                   nullable=True)

    # 收款地址
    payment_address = db.Column(db.String(255), nullable=True)

    # 完成结果
    result = db.Column(db.Text, nullable=True)

    # team = db.relationship('ProposalClaimTeam',
    #                        foreign_keys='ProposalClaimTeam.team_id',
    #                        backref='team',
    #                        lazy='dynamic')

    @property
    def status_key(self):
        if self.status:
            return ProposalClaimStatus(self.status).name

    @property
    def team(self):
        return ProposalClaimTeam.query.filter_by(team_id=self.id, is_delete=0)
Exemplo n.º 7
0
class Proposal(BaseModelMixin, TimestampMixin, db.Model):
    """
    Proposal
    """

    __tablename__ = 'proposal'

    zone_id = db.Column(db.Integer, db.ForeignKey('proposal_zone.id'))
    zone_proposal_id = db.Column(
        db.Integer)  # 该 proposal 在某专区内的 ID, 以在该专区内的 ID 为自增
    title = db.Column(db.String(200))
    tag = db.Column(db.String(200))
    amount = db.Column(db.DECIMAL)
    currency_id = db.Column(db.Integer,
                            db.ForeignKey('currency.id'),
                            nullable=True)
    summary = db.Column(db.String(200))
    detail = db.Column(db.Text)
    status = db.Column(db.Integer)

    # 注意,backref 不能跟 talename 重名
    comments = db.relationship('Comment',
                               foreign_keys='Comment.proposal_id',
                               backref='link_proposal',
                               lazy='dynamic')

    def __repr__(self):
        return "<Proposal '{}'>".format(self.title)

    def zone(self):
        return ProposalZone.query.filter(zone=self).first()

    def creator(self):
        return User.query.filter(creator=self).first()

    def currency_unit(self):
        return Currency.query.filter(currency_unit=self).first()
Exemplo n.º 8
0
 def creator_id(cls):
     return db.Column(db.Integer, db.ForeignKey('user.id'))
Exemplo n.º 9
0
class Proposal(BaseModelMixin, TimestampMixin, db.Model):
    """
    Proposal
    """

    __tablename__ = 'proposal'

    zone_id = db.Column(db.Integer, db.ForeignKey('proposal_zone.id'))
    zone_proposal_id = db.Column(
        db.Integer)  # 该 proposal 在某专区内的 ID, 以在该专区内的 ID 为自增
    title = db.Column(db.String(200))
    category_id = db.Column(db.Integer,
                            db.ForeignKey('category.id'),
                            nullable=True)
    tag = db.Column(db.String(200))
    amount = db.Column(db.DECIMAL)

    # 前端上,只能选择该专区支持的代币
    currency_id = db.Column(db.Integer,
                            db.ForeignKey('currency.id'),
                            nullable=True)
    summary = db.Column(db.String(200))
    detail = db.Column(db.Text)

    # 提案状态

    # 100 待投票: 创建后第一个状态,此时还未上链
    # 200 立项投票中: 上链成功, 在规定投票时间内进行链上投票
    # 300 申领中: 如果投票通过, 提案状态自动改变(投票结束时达成条件)
    # 400 投票未通过: 在规定投票时内, 没有达成通过条件, 状态自动改变
    # 以下是 status=300 后才会有的状态
    # 500 进行中: 由(专区)管理员修改到此状态
    # 600 验收中: 由(专区)管理员修改到此状态,此时需要进行多签投票,决定提案是否验收
    # 700 已完成: 如果投票通过, 提案状态自动改变(投票结束时达成条件)
    # 800 失败: 验收投票不通过, 提案状态自动改变(投票结束时达成条件)
    status = db.Column(db.Integer)

    # 是否已经上链
    # onchain = db.Column(db.Boolean, default=False)

    # 上链后的 hash
    onchain_hash = db.Column(db.String(500))

    # 预计工时
    estimated_hours = db.Column(db.Integer, nullable=True)

    # 投票开始时间, 默认是创建后马上开始
    vote_start_time = db.Column(db.DateTime, default=datetime.utcnow)

    # 投票最大持续时间
    vote_duration_hours = db.Column(
        db.Integer, default=7200)  # vote default duration: 7200min=5day

    # 注意,backref 不能跟 talename 重名
    comments = db.relationship('Comment',
                               foreign_keys='Comment.proposal_id',
                               backref='link_proposal',
                               lazy='dynamic')

    logs = db.relationship('ProposalLog',
                           foreign_keys='ProposalLog.proposal_id',
                           backref='proposal',
                           lazy='dynamic')

    claims = db.relationship('ProposalClaim',
                             foreign_keys='ProposalClaim.proposal_id',
                             backref='proposal',
                             lazy='dynamic')

    def __repr__(self):
        return "<Proposal '{}'>".format(self.title)

    # 加上 @property 注解,表示这是一个属性字段
    # @property
    # def comments_count(self):
    #     return Comment.query.with_parent(self).filter_by(is_delete=0).count()

    def set_onchain_hash(self):
        self.onchain_hash = md5(
            str([
                self.id, self.title, self.summary, self.status,
                self.creator_id, self.created
            ]))

    @property
    def status_key(self):
        if self.status:
            return ProposalStatus(self.status).name

    @hybrid_property
    def comments_count(self):
        return self.comments.filter_by(is_delete=0).count()

    @comments_count.expression
    def comments_count(cls):
        return (select([func.count(Comment.id)]).where(
            and_(Comment.proposal_id == cls.id, Comment.is_delete == 0)))